Auto merge of #68031 - Marwes:fold_list, r=estebank

perf: Avoid creating a SmallVec if nothing changes during a fold

Not sure if this helps but in theory it should be less work than what
the current micro optimization does for `ty::Predicate` lists.

(It would explain the overhead I am seeing from `perf`.)
diff --git a/.gitignore b/.gitignore
index 1428ee6..d9761ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,14 +34,7 @@
 # Created by default with `src/ci/docker/run.sh`:
 /obj/
 /rustllvm/
-/src/libcore/unicode/DerivedCoreProperties.txt
-/src/libcore/unicode/DerivedNormalizationProps.txt
-/src/libcore/unicode/PropList.txt
-/src/libcore/unicode/ReadMe.txt
-/src/libcore/unicode/Scripts.txt
-/src/libcore/unicode/SpecialCasing.txt
-/src/libcore/unicode/UnicodeData.txt
-/src/libcore/unicode/downloaded
+/unicode-downloads
 /target/
 # Generated by compiletest for incremental:
 /tmp/
diff --git a/.gitmodules b/.gitmodules
index 31db077..003e50d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -15,13 +15,13 @@
 	url = https://github.com/rust-lang/book.git
 [submodule "src/tools/rls"]
 	path = src/tools/rls
-	url = https://github.com/rust-lang-nursery/rls.git
+	url = https://github.com/rust-lang/rls.git
 [submodule "src/tools/clippy"]
 	path = src/tools/clippy
-	url = https://github.com/rust-lang-nursery/rust-clippy.git
+	url = https://github.com/rust-lang/rust-clippy.git
 [submodule "src/tools/rustfmt"]
 	path = src/tools/rustfmt
-	url = https://github.com/rust-lang-nursery/rustfmt.git
+	url = https://github.com/rust-lang/rustfmt.git
 [submodule "src/tools/miri"]
 	path = src/tools/miri
 	url = https://github.com/rust-lang/miri.git
@@ -40,7 +40,7 @@
 [submodule "src/llvm-project"]
 	path = src/llvm-project
 	url = https://github.com/rust-lang/llvm-project.git
-	branch = rustc/9.0-2019-09-19
+	branch = rustc/9.0-2019-12-19
 [submodule "src/doc/embedded-book"]
 	path = src/doc/embedded-book
 	url = https://github.com/rust-embedded/book.git
diff --git a/.mailmap b/.mailmap
index 1634c2d..6ab6be2 100644
--- a/.mailmap
+++ b/.mailmap
@@ -211,6 +211,7 @@
 Phil Dawes <phil@phildawes.net> Phil Dawes <pdawes@drw.com>
 Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
 Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch>
+Philipp Krones <hello@philkrones.com> flip1995 <hello@philkrones.com>
 Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
 Przemysław Wesołek <jest@go.art.pl> Przemek Wesołek <jest@go.art.pl>
 Rafael Ávila de Espíndola <respindola@mozilla.com> Rafael Avila de Espindola <espindola@dream.(none)>
diff --git a/Cargo.lock b/Cargo.lock
index 274c1ee..9c359b4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -21,7 +21,7 @@
 dependencies = [
  "compiler_builtins",
  "core",
- "rand 0.7.0",
+ "rand 0.7.3",
  "rand_xorshift 0.2.0",
 ]
 
@@ -32,7 +32,7 @@
 checksum = "9e266e1f4be5ffa05309f650e2586fe1d3ae6034eb24025a7ae1dfecc330823a"
 dependencies = [
  "html5ever",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "maplit",
  "matches",
  "tendril",
@@ -58,6 +58,12 @@
 ]
 
 [[package]]
+name = "anyhow"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
+
+[[package]]
 name = "arc-swap"
 version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -109,9 +115,9 @@
 
 [[package]]
 name = "autocfg"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
+checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
 
 [[package]]
 name = "backtrace"
@@ -193,7 +199,7 @@
  "filetime",
  "getopts",
  "ignore",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "libc",
  "num_cpus",
  "pretty_assertions",
@@ -201,6 +207,7 @@
  "serde_json",
  "time",
  "toml",
+ "winapi 0.3.8",
 ]
 
 [[package]]
@@ -265,11 +272,10 @@
 
 [[package]]
 name = "c2-chacha"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
+checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
 dependencies = [
- "lazy_static 1.3.0",
  "ppv-lite86",
 ]
 
@@ -277,6 +283,7 @@
 name = "cargo"
 version = "0.43.0"
 dependencies = [
+ "anyhow",
  "atty",
  "bytesize",
  "cargo-platform",
@@ -290,7 +297,6 @@
  "curl",
  "curl-sys",
  "env_logger 0.7.1",
- "failure",
  "filetime",
  "flate2",
  "fs2",
@@ -300,11 +306,11 @@
  "glob",
  "hex 0.4.0",
  "home",
- "humantime",
+ "humantime 2.0.0",
  "ignore",
  "im-rc",
  "jobserver",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "lazycell",
  "libc",
  "libgit2-sys",
@@ -318,7 +324,7 @@
  "pretty_env_logger",
  "remove_dir_all",
  "rustc-workspace-hack",
- "rustfix",
+ "rustfix 0.5.0",
  "same-file",
  "semver",
  "serde",
@@ -357,7 +363,7 @@
  "flate2",
  "git2",
  "glob",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "remove_dir_all",
  "serde_json",
  "tar",
@@ -395,19 +401,18 @@
 
 [[package]]
 name = "cc"
-version = "1.0.49"
+version = "1.0.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e"
+checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
 dependencies = [
  "jobserver",
- "num_cpus",
 ]
 
 [[package]]
 name = "cfg-if"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89431bba4e6b7092fb5fcd00a6f6ca596c55cc26b2f1e6dcdd08a1f4933f66b2"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -469,7 +474,7 @@
  "compiletest_rs",
  "derive-new",
  "git2",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "regex",
  "rustc-workspace-hack",
  "rustc_tools_util 0.2.0",
@@ -490,7 +495,7 @@
  "cargo_metadata 0.9.0",
  "if_chain",
  "itertools 0.8.0",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "matches",
  "pulldown-cmark 0.6.1",
  "quine-mc_cluskey",
@@ -514,9 +519,9 @@
 
 [[package]]
 name = "cmake"
-version = "0.1.38"
+version = "0.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96210eec534fc3fbfc0452a63769424eaa80205fda6cea98e5b61cb3d97bcec8"
+checksum = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
 dependencies = [
  "cc",
 ]
@@ -570,9 +575,9 @@
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.22"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6f083abf9bb9005a27d2da62706f661245278cb7096da37ab27410eaf60f2c1"
+checksum = "b9975aefa63997ef75ca9cf013ff1bb81487aaa0b622c21053afd3b92979a7af"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -585,12 +590,12 @@
  "diff",
  "env_logger 0.7.1",
  "getopts",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "libc",
  "log",
  "miow 0.3.3",
  "regex",
- "rustfix",
+ "rustfix 0.5.0",
  "serde",
  "serde_json",
  "walkdir",
@@ -610,7 +615,7 @@
  "log",
  "miow 0.3.3",
  "regex",
- "rustfix",
+ "rustfix 0.4.6",
  "serde",
  "serde_derive",
  "serde_json",
@@ -657,7 +662,7 @@
 name = "core"
 version = "0.0.0"
 dependencies = [
- "rand 0.7.0",
+ "rand 0.7.3",
 ]
 
 [[package]]
@@ -694,10 +699,10 @@
 
 [[package]]
 name = "crates-io"
-version = "0.30.0"
+version = "0.31.0"
 dependencies = [
+ "anyhow",
  "curl",
- "failure",
  "percent-encoding 2.1.0",
  "serde",
  "serde_derive",
@@ -743,7 +748,7 @@
  "arrayvec",
  "cfg-if",
  "crossbeam-utils 0.6.5",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "memoffset",
  "scopeguard",
 ]
@@ -764,7 +769,7 @@
 checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
 dependencies = [
  "cfg-if",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
 ]
 
 [[package]]
@@ -775,7 +780,7 @@
 dependencies = [
  "autocfg",
  "cfg-if",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
 ]
 
 [[package]]
@@ -792,9 +797,9 @@
 
 [[package]]
 name = "curl"
-version = "0.4.24"
+version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d08ad3cb89d076a36b0ce5749eec2c9964f70c0c58480ab6b75a91ec4fc206d8"
+checksum = "06aa71e9208a54def20792d877bc663d6aae0732b9852e612c4a933177c31283"
 dependencies = [
  "curl-sys",
  "libc",
@@ -807,9 +812,9 @@
 
 [[package]]
 name = "curl-sys"
-version = "0.4.22"
+version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e9a9a4e417722876332136a00cacf92c2ceb331fab4b52b6a1ad16c6cd79255"
+checksum = "0c38ca47d60b86d0cc9d42caa90a0885669c2abc9791f871c81f58cdf39e979b"
 dependencies = [
  "cc",
  "libc",
@@ -972,7 +977,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "regex",
  "serde",
  "serde_derive",
@@ -1006,7 +1011,7 @@
 checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
 dependencies = [
  "atty",
- "humantime",
+ "humantime 1.3.0",
  "log",
  "regex",
  "termcolor",
@@ -1019,7 +1024,7 @@
 checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
 dependencies = [
  "atty",
- "humantime",
+ "humantime 1.3.0",
  "log",
  "regex",
  "termcolor",
@@ -1238,13 +1243,13 @@
 
 [[package]]
 name = "getrandom"
-version = "0.1.12"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
+checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi 0.7.0",
+ "wasi",
 ]
 
 [[package]]
@@ -1322,7 +1327,7 @@
 checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
 dependencies = [
  "hashbrown 0.5.0",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "pest",
  "pest_derive",
@@ -1448,6 +1453,12 @@
 ]
 
 [[package]]
+name = "humantime"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9b6c53306532d3c8e8087b44e6580e10db51a023cf9b433cea2ac38066b92da"
+
+[[package]]
 name = "hyper"
 version = "0.12.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1532,7 +1543,7 @@
 dependencies = [
  "crossbeam-channel",
  "globset",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "memchr",
  "regex",
@@ -1569,7 +1580,7 @@
  "clap",
  "failure",
  "flate2",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "num_cpus",
  "rayon",
  "remove_dir_all",
@@ -1581,12 +1592,11 @@
 
 [[package]]
 name = "iovec"
-version = "0.1.2"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
 dependencies = [
  "libc",
- "winapi 0.2.8",
 ]
 
 [[package]]
@@ -1632,13 +1642,11 @@
 
 [[package]]
 name = "jobserver"
-version = "0.1.16"
+version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10"
+checksum = "67b06c1b455f1cf4269a8cfc320ab930a810e2375a42af5075eb8a8b36405ce0"
 dependencies = [
  "libc",
- "log",
- "rand 0.7.0",
 ]
 
 [[package]]
@@ -1735,7 +1743,7 @@
  "bytes",
  "globset",
  "jsonrpc-core",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "num_cpus",
  "tokio",
@@ -1761,9 +1769,9 @@
 
 [[package]]
 name = "lazy_static"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "lazycell"
@@ -1796,9 +1804,9 @@
 
 [[package]]
 name = "libnghttp2-sys"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4"
+checksum = "02254d44f4435dd79e695f2c2b83cd06a47919adea30216ceaf0c57ca0a72463"
 dependencies = [
  "cc",
  "libc",
@@ -1806,9 +1814,9 @@
 
 [[package]]
 name = "libssh2-sys"
-version = "0.2.11"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
+checksum = "36aa6e813339d3a063292b77091dfbbb6152ff9006a459895fa5bebed7d34f10"
 dependencies = [
  "cc",
  "libc",
@@ -1858,7 +1866,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
 ]
 
 [[package]]
@@ -1951,7 +1959,7 @@
  "error-chain",
  "handlebars",
  "itertools 0.8.0",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "memchr",
  "open",
@@ -1995,9 +2003,9 @@
 
 [[package]]
 name = "measureme"
-version = "0.5.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8"
+checksum = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932"
 dependencies = [
  "byteorder",
  "memmap",
@@ -2145,7 +2153,7 @@
  "hex 0.4.0",
  "log",
  "num-traits",
- "rand 0.7.0",
+ "rand 0.7.3",
  "rustc-workspace-hack",
  "rustc_version",
  "serde",
@@ -2159,7 +2167,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "libc",
  "log",
  "openssl",
@@ -2248,7 +2256,7 @@
  "bitflags",
  "cfg-if",
  "foreign-types",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "libc",
  "openssl-sys",
 ]
@@ -2261,18 +2269,18 @@
 
 [[package]]
 name = "openssl-src"
-version = "111.6.0+1.1.1d"
+version = "111.6.1+1.1.1d"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9c2da1de8a7a3f860919c01540b03a6db16de042405a8a07a5e9d0b4b825d9c"
+checksum = "c91b04cb43c1a8a90e934e0cd612e2a5715d976d2d6cff4490278a0cddf35005"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.52"
+version = "0.9.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc"
+checksum = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f"
 dependencies = [
  "autocfg",
  "cc",
@@ -2329,7 +2337,7 @@
  "log",
  "mio-named-pipes",
  "miow 0.3.3",
- "rand 0.7.0",
+ "rand 0.7.3",
  "tokio",
  "tokio-named-pipes",
  "tokio-uds",
@@ -2457,9 +2465,9 @@
 
 [[package]]
 name = "pkg-config"
-version = "0.3.14"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
+checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
 
 [[package]]
 name = "polonius-engine"
@@ -2474,9 +2482,9 @@
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
+checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
 
 [[package]]
 name = "precomputed-hash"
@@ -2567,7 +2575,7 @@
 dependencies = [
  "error-chain",
  "idna 0.2.0",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "regex",
  "url 2.1.0",
 ]
@@ -2641,8 +2649,8 @@
  "clap",
  "derive_more",
  "env_logger 0.6.2",
- "humantime",
- "lazy_static 1.3.0",
+ "humantime 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "rls-span",
  "rustc-ap-syntax",
@@ -2669,9 +2677,9 @@
 
 [[package]]
 name = "rand"
-version = "0.7.0"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
 dependencies = [
  "getrandom",
  "libc",
@@ -2819,7 +2827,7 @@
  "crossbeam-deque",
  "crossbeam-queue",
  "crossbeam-utils 0.6.5",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "num_cpus",
 ]
 
@@ -2834,9 +2842,9 @@
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.43"
+version = "0.1.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d"
+checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
 
 [[package]]
 name = "redox_termios"
@@ -2936,26 +2944,26 @@
 name = "rls"
 version = "1.41.0"
 dependencies = [
+ "anyhow",
  "cargo",
  "cargo_metadata 0.8.0",
  "clippy_lints",
  "crossbeam-channel",
  "difference",
  "env_logger 0.7.1",
- "failure",
  "futures",
  "heck",
  "home",
  "itertools 0.8.0",
  "jsonrpc-core",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "lsp-codec",
  "lsp-types",
  "num_cpus",
  "ordslice",
  "racer",
- "rand 0.7.0",
+ "rand 0.7.3",
  "rayon",
  "regex",
  "rls-analysis",
@@ -3028,7 +3036,7 @@
  "failure",
  "futures",
  "log",
- "rand 0.7.0",
+ "rand 0.7.3",
  "rls-data",
  "rls-ipc",
  "serde",
@@ -3080,17 +3088,14 @@
  "jobserver",
  "log",
  "measureme",
- "num_cpus",
  "parking_lot",
  "polonius-engine",
  "rustc-rayon",
  "rustc-rayon-core",
  "rustc_apfloat",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
- "rustc_fs_util",
  "rustc_hir",
  "rustc_index",
  "rustc_macros",
@@ -3130,7 +3135,7 @@
  "ena",
  "indexmap",
  "jobserver",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "parking_lot",
  "rustc-ap-graphviz",
@@ -3223,7 +3228,7 @@
 checksum = "61fc1c901d2cbd24cae95d7bc5a58aa7661ec3dc5320c78c32830a52a685c33c"
 dependencies = [
  "bitflags",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "rustc-ap-rustc_data_structures",
  "rustc-ap-rustc_errors",
@@ -3278,7 +3283,6 @@
  "jemalloc-sys",
  "rustc_codegen_ssa",
  "rustc_driver",
- "rustc_target",
 ]
 
 [[package]]
@@ -3301,7 +3305,7 @@
  "crossbeam-deque",
  "crossbeam-queue",
  "crossbeam-utils 0.6.5",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "num_cpus",
 ]
 
@@ -3349,24 +3353,12 @@
 ]
 
 [[package]]
-name = "rustc_asan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_ast_lowering"
 version = "0.0.0"
 dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3378,17 +3370,31 @@
 ]
 
 [[package]]
+name = "rustc_ast_passes"
+version = "0.0.0"
+dependencies = [
+ "log",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_feature",
+ "rustc_parse",
+ "rustc_session",
+ "rustc_span",
+ "syntax",
+]
+
+[[package]]
 name = "rustc_builtin_macros"
 version = "0.0.0"
 dependencies = [
  "fmt_macros",
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "smallvec 1.0.0",
@@ -3409,7 +3415,6 @@
  "rustc_codegen_utils",
  "rustc_data_structures",
  "rustc_errors",
- "rustc_expand",
  "rustc_feature",
  "rustc_fs_util",
  "rustc_hir",
@@ -3419,6 +3424,7 @@
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "serialize",
  "smallvec 1.0.0",
  "syntax",
 ]
@@ -3438,7 +3444,6 @@
  "rustc_apfloat",
  "rustc_codegen_utils",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_fs_util",
  "rustc_hir",
@@ -3479,7 +3484,7 @@
  "graphviz",
  "indexmap",
  "jobserver",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "measureme",
  "parking_lot",
@@ -3490,6 +3495,7 @@
  "serialize",
  "smallvec 1.0.0",
  "stable_deref_trait",
+ "winapi 0.3.8",
 ]
 
 [[package]]
@@ -3497,8 +3503,7 @@
 version = "0.0.0"
 dependencies = [
  "env_logger 0.7.1",
- "graphviz",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "rustc",
  "rustc_codegen_utils",
@@ -3513,12 +3518,12 @@
  "rustc_mir",
  "rustc_parse",
  "rustc_plugin_impl",
- "rustc_resolve",
  "rustc_save_analysis",
  "rustc_span",
  "rustc_target",
  "serialize",
  "syntax",
+ "winapi 0.3.8",
 ]
 
 [[package]]
@@ -3538,6 +3543,7 @@
  "term_size",
  "termcolor",
  "unicode-width",
+ "winapi 0.3.8",
 ]
 
 [[package]]
@@ -3545,11 +3551,13 @@
 version = "0.0.0"
 dependencies = [
  "log",
+ "rustc_ast_passes",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "serialize",
  "smallvec 1.0.0",
@@ -3560,7 +3568,7 @@
 name = "rustc_feature"
 version = "0.0.0"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "rustc_data_structures",
  "rustc_span",
 ]
@@ -3591,7 +3599,7 @@
 dependencies = [
  "graphviz",
  "log",
- "rand 0.7.0",
+ "rand 0.7.3",
  "rustc",
  "rustc_data_structures",
  "rustc_fs_util",
@@ -3619,6 +3627,7 @@
  "rustc",
  "rustc-rayon",
  "rustc_ast_lowering",
+ "rustc_ast_passes",
  "rustc_builtin_macros",
  "rustc_codegen_llvm",
  "rustc_codegen_ssa",
@@ -3631,19 +3640,23 @@
  "rustc_lint",
  "rustc_metadata",
  "rustc_mir",
+ "rustc_mir_build",
  "rustc_parse",
  "rustc_passes",
  "rustc_plugin_impl",
  "rustc_privacy",
  "rustc_resolve",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "rustc_traits",
+ "rustc_ty",
  "rustc_typeck",
  "serialize",
  "smallvec 1.0.0",
  "syntax",
  "tempfile",
+ "winapi 0.3.8",
 ]
 
 [[package]]
@@ -3660,7 +3673,7 @@
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
+ "rustc_errors",
  "rustc_feature",
  "rustc_hir",
  "rustc_index",
@@ -3681,17 +3694,6 @@
 ]
 
 [[package]]
-name = "rustc_lsan"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
 name = "rustc_macros"
 version = "0.1.0"
 dependencies = [
@@ -3711,7 +3713,6 @@
  "memmap",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_hir",
@@ -3723,13 +3724,13 @@
  "smallvec 1.0.0",
  "stable_deref_trait",
  "syntax",
+ "winapi 0.3.8",
 ]
 
 [[package]]
 name = "rustc_mir"
 version = "0.0.0"
 dependencies = [
- "arena",
  "either",
  "graphviz",
  "itertools 0.8.0",
@@ -3739,7 +3740,6 @@
  "rustc",
  "rustc_apfloat",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3753,14 +3753,25 @@
 ]
 
 [[package]]
-name = "rustc_msan"
+name = "rustc_mir_build"
 version = "0.0.0"
 dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
+ "arena",
+ "itertools 0.8.0",
+ "log",
+ "rustc",
+ "rustc_apfloat",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_macros",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "serialize",
+ "smallvec 1.0.0",
+ "syntax",
 ]
 
 [[package]]
@@ -3770,10 +3781,10 @@
  "bitflags",
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
+ "rustc_session",
  "rustc_span",
  "smallvec 1.0.0",
  "syntax",
@@ -3787,12 +3798,11 @@
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_hir",
  "rustc_index",
- "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "syntax",
@@ -3803,8 +3813,9 @@
 version = "0.0.0"
 dependencies = [
  "rustc",
- "rustc_error_codes",
+ "rustc_errors",
  "rustc_hir",
+ "rustc_lint",
  "rustc_metadata",
  "rustc_span",
  "syntax",
@@ -3817,7 +3828,7 @@
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
+ "rustc_errors",
  "rustc_hir",
  "rustc_span",
  "rustc_typeck",
@@ -3834,7 +3845,6 @@
  "rustc",
  "rustc_ast_lowering",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
@@ -3934,14 +3944,14 @@
 ]
 
 [[package]]
-name = "rustc_tsan"
+name = "rustc_ty"
 version = "0.0.0"
 dependencies = [
- "alloc",
- "build_helper",
- "cmake",
- "compiler_builtins",
- "core",
+ "log",
+ "rustc",
+ "rustc_data_structures",
+ "rustc_hir",
+ "rustc_span",
 ]
 
 [[package]]
@@ -3952,7 +3962,6 @@
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -4008,6 +4017,18 @@
 ]
 
 [[package]]
+name = "rustfix"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "804b11883a5ce0ad0378fbf95a8dea59ee6b51c331a73b8f471b6bdaa3bd40c1"
+dependencies = [
+ "anyhow",
+ "log",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
 name = "rustfmt-config_proc_macro"
 version = "0.2.0"
 dependencies = [
@@ -4032,7 +4053,7 @@
  "getopts",
  "ignore",
  "itertools 0.8.0",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "regex",
  "rustc-ap-rustc_target",
@@ -4067,11 +4088,11 @@
 
 [[package]]
 name = "schannel"
-version = "0.1.14"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56"
+checksum = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "winapi 0.3.8",
 ]
 
@@ -4271,9 +4292,9 @@
 
 [[package]]
 name = "socket2"
-version = "0.3.8"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
+checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
 dependencies = [
  "cfg-if",
  "libc",
@@ -4304,13 +4325,9 @@
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
- "rand 0.7.0",
- "rustc_asan",
- "rustc_lsan",
- "rustc_msan",
- "rustc_tsan",
+ "rand 0.7.3",
  "unwind",
- "wasi 0.9.0+wasi-snapshot-preview1",
+ "wasi",
 ]
 
 [[package]]
@@ -4328,7 +4345,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "new_debug_unreachable",
  "phf_shared",
  "precomputed-hash",
@@ -4462,11 +4479,8 @@
 name = "syntax"
 version = "0.0.0"
 dependencies = [
- "bitflags",
- "lazy_static 1.3.0",
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_index",
@@ -4499,7 +4513,7 @@
 dependencies = [
  "cfg-if",
  "libc",
- "rand 0.7.0",
+ "rand 0.7.3",
  "redox_syscall",
  "remove_dir_all",
  "winapi 0.3.8",
@@ -4606,14 +4620,14 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
 ]
 
 [[package]]
 name = "tidy"
 version = "0.1.0"
 dependencies = [
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "regex",
  "serde",
  "serde_json",
@@ -4740,7 +4754,7 @@
 dependencies = [
  "crossbeam-queue",
  "futures",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "libc",
  "log",
  "mio",
@@ -4759,7 +4773,7 @@
 dependencies = [
  "crossbeam-utils 0.6.5",
  "futures",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "mio",
  "num_cpus",
@@ -4830,7 +4844,7 @@
  "crossbeam-queue",
  "crossbeam-utils 0.6.5",
  "futures",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "log",
  "num_cpus",
  "slab",
@@ -4900,7 +4914,7 @@
  "failure",
  "failure_derive",
  "is-match",
- "lazy_static 1.3.0",
+ "lazy_static 1.4.0",
  "regex",
  "toml",
  "toml-query_derive",
@@ -4939,6 +4953,16 @@
 checksum = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
 
 [[package]]
+name = "ucd-parse"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca6b52bf4da6512f0f07785a04769222e50d29639e7ecd016b7806fd2de306b4"
+dependencies = [
+ "lazy_static 1.4.0",
+ "regex",
+]
+
+[[package]]
 name = "ucd-trie"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4960,6 +4984,13 @@
 ]
 
 [[package]]
+name = "unicode-bdd"
+version = "0.1.0"
+dependencies = [
+ "ucd-parse",
+]
+
+[[package]]
 name = "unicode-bidi"
 version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5098,9 +5129,9 @@
 
 [[package]]
 name = "vcpkg"
-version = "0.2.6"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
+checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
 
 [[package]]
 name = "vec_map"
@@ -5164,12 +5195,6 @@
 
 [[package]]
 name = "wasi"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
-
-[[package]]
-name = "wasi"
 version = "0.9.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
diff --git a/Cargo.toml b/Cargo.toml
index a242f09..9d5c27b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,6 +23,7 @@
   "src/tools/rustfmt",
   "src/tools/miri",
   "src/tools/rustdoc-themes",
+  "src/tools/unicode-table-generator",
 ]
 exclude = [
   "build",
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
index 16fe87b..1b5ec8b 100644
--- a/LICENSE-APACHE
+++ b/LICENSE-APACHE
@@ -174,28 +174,3 @@
    of your accepting any such warranty or additional liability.
 
 END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/config.toml.example b/config.toml.example
index bfd9e18..c9e1733 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -181,21 +181,23 @@
 # Indicate whether the vendored sources are used for Rust dependencies or not
 #vendor = false
 
-# Typically the build system will build the rust compiler twice. The second
+# Typically the build system will build the Rust compiler twice. The second
 # compiler, however, will simply use its own libraries to link against. If you
 # would rather to perform a full bootstrap, compiling the compiler three times,
 # then you can set this option to true. You shouldn't ever need to set this
 # option to true.
 #full-bootstrap = false
 
-# Enable a build of the extended rust tool set which is not only the compiler
+# Enable a build of the extended Rust tool set which is not only the compiler
 # but also tools such as Cargo. This will also produce "combined installers"
 # which are used to install Rust and Cargo together. This is disabled by
-# default.
+# default. The `tools` option (immediately below) specifies which tools should
+# be built if `extended = true`.
 #extended = false
 
-# Installs chosen set of extended tools if enabled. By default builds all.
-# If chosen tool failed to build the installation fails.
+# Installs chosen set of extended tools if `extended = true`. By default builds all.
+# If chosen tool failed to build the installation fails. If `extended = false`, this
+# option is ignored.
 #tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"]
 
 # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 3ab00a6..c09f58c 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -49,5 +49,9 @@
 time = "0.1"
 ignore = "0.4.10"
 
+[target.'cfg(windows)'.dependencies.winapi]
+version = "0.3"
+features = ["fileapi", "ioapiset", "jobapi2", "handleapi", "winioctl"]
+
 [dev-dependencies]
 pretty_assertions = "0.5"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index f7d8daa..d9c894a 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -343,6 +343,7 @@
                 tool::Rustdoc,
                 tool::Clippy,
                 native::Llvm,
+                native::Sanitizers,
                 tool::Rustfmt,
                 tool::Miri,
                 native::Lld
@@ -726,7 +727,7 @@
             self.clear_if_dirty(&my_out, &rustdoc);
         }
 
-        cargo.env("CARGO_TARGET_DIR", out_dir).arg(cmd).arg("-Zconfig-profile");
+        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile");
 
         let profile_var = |name: &str| {
             let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
@@ -865,6 +866,18 @@
         let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot };
         let libdir = self.rustc_libdir(compiler);
 
+        // Clear the output directory if the real rustc we're using has changed;
+        // Cargo cannot detect this as it thinks rustc is bootstrap/debug/rustc.
+        //
+        // Avoid doing this during dry run as that usually means the relevant
+        // compiler is not yet linked/copied properly.
+        //
+        // Only clear out the directory if we're compiling std; otherwise, we
+        // should let Cargo take care of things for us (via depdep info)
+        if !self.config.dry_run && mode == Mode::Std && cmd == "build" {
+            self.clear_if_dirty(&out_dir, &self.rustc(compiler));
+        }
+
         // Customize the compiler we're running. Specify the compiler to cargo
         // as our shim and then pass it some various options used to configure
         // how the actual compiler itself is called.
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index d4016f1..b7651576 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -45,7 +45,7 @@
         let compiler = builder.compiler(0, builder.config.build);
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind));
-        std_cargo(builder, &compiler, target, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
         run_cargo(
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 2d60024..eced035 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -87,7 +87,7 @@
         target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
 
         let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
-        std_cargo(builder, &compiler, target, &mut cargo);
+        std_cargo(builder, target, &mut cargo);
 
         builder.info(&format!(
             "Building stage{} std artifacts ({} -> {})",
@@ -153,17 +153,18 @@
         copy_and_stamp(Path::new(&src), "libunwind.a");
     }
 
+    if builder.config.sanitizers && compiler.stage != 0 {
+        // The sanitizers are only copied in stage1 or above,
+        // to avoid creating dependency on LLVM.
+        target_deps.extend(copy_sanitizers(builder, &compiler, target));
+    }
+
     target_deps
 }
 
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
-pub fn std_cargo(
-    builder: &Builder<'_>,
-    compiler: &Compiler,
-    target: Interned<String>,
-    cargo: &mut Cargo,
-) {
+pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, cargo: &mut Cargo) {
     if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
@@ -206,19 +207,6 @@
         let mut features = builder.std_features();
         features.push_str(&compiler_builtins_c_feature);
 
-        if compiler.stage != 0 && builder.config.sanitizers {
-            // This variable is used by the sanitizer runtime crates, e.g.
-            // rustc_lsan, to build the sanitizer runtime from C code
-            // When this variable is missing, those crates won't compile the C code,
-            // so we don't set this variable during stage0 where llvm-config is
-            // missing
-            // We also only build the runtimes when --enable-sanitizers (or its
-            // config.toml equivalent) is used
-            let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
-            cargo.env("LLVM_CONFIG", llvm_config);
-            cargo.env("RUSTC_BUILD_SANITIZERS", "1");
-        }
-
         cargo
             .arg("--features")
             .arg(features)
@@ -276,31 +264,43 @@
         let libdir = builder.sysroot_libdir(target_compiler, target);
         let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
         add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
-
-        if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
-            // The sanitizers are only built in stage1 or above, so the dylibs will
-            // be missing in stage0 and causes panic. See the `std()` function above
-            // for reason why the sanitizers are not built in stage0.
-            copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
-        }
     }
 }
 
-fn copy_apple_sanitizer_dylibs(
+/// Copies sanitizer runtime libraries into target libdir.
+fn copy_sanitizers(
     builder: &Builder<'_>,
-    native_dir: &Path,
-    platform: &str,
-    into: &Path,
-) {
-    for &sanitizer in &["asan", "tsan"] {
-        let filename = format!("lib__rustc__clang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
-        let mut src_path = native_dir.join(sanitizer);
-        src_path.push("build");
-        src_path.push("lib");
-        src_path.push("darwin");
-        src_path.push(&filename);
-        builder.copy(&src_path, &into.join(filename));
+    compiler: &Compiler,
+    target: Interned<String>,
+) -> Vec<PathBuf> {
+    let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
+
+    if builder.config.dry_run {
+        return Vec::new();
     }
+
+    let mut target_deps = Vec::new();
+    let libdir = builder.sysroot_libdir(*compiler, target);
+
+    for runtime in &runtimes {
+        let dst = libdir.join(&runtime.name);
+        builder.copy(&runtime.path, &dst);
+
+        if target == "x86_64-apple-darwin" {
+            // Update the library install name reflect the fact it has been renamed.
+            let status = Command::new("install_name_tool")
+                .arg("-id")
+                .arg(format!("@rpath/{}", runtime.name))
+                .arg(&dst)
+                .status()
+                .expect("failed to execute `install_name_tool`");
+            assert!(status.success());
+        }
+
+        target_deps.push(dst);
+    }
+
+    target_deps
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -776,7 +776,6 @@
         let bindir = sysroot.join("bin");
         t!(fs::create_dir_all(&bindir));
         let compiler = builder.rustc(target_compiler);
-        let _ = fs::remove_file(&compiler);
         builder.copy(&rustc, &compiler);
 
         target_compiler
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 944df66..110c8b8 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -493,9 +493,13 @@
             config.mandir = install.mandir.clone().map(PathBuf::from);
         }
 
+        // We want the llvm-skip-rebuild flag to take precedence over the
+        // skip-rebuild config.toml option so we store it separately
+        // so that we can infer the right value
+        let mut llvm_skip_rebuild = flags.llvm_skip_rebuild;
+
         // Store off these values as options because if they're not provided
         // we'll infer default values for them later
-        let mut llvm_skip_rebuild = None;
         let mut llvm_assertions = None;
         let mut debug = None;
         let mut debug_assertions = None;
@@ -517,7 +521,7 @@
             }
             set(&mut config.ninja, llvm.ninja);
             llvm_assertions = llvm.assertions;
-            llvm_skip_rebuild = llvm.skip_rebuild;
+            llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild);
             set(&mut config.llvm_optimize, llvm.optimize);
             set(&mut config.llvm_thin_lto, llvm.thin_lto);
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index e64d4c8..8d13df3 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -984,10 +984,6 @@
             "src/libcore",
             "src/libpanic_abort",
             "src/libpanic_unwind",
-            "src/librustc_asan",
-            "src/librustc_lsan",
-            "src/librustc_msan",
-            "src/librustc_tsan",
             "src/libstd",
             "src/libunwind",
             "src/libtest",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 8cd7fc2..2040565 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -49,7 +49,7 @@
                 builder.ensure(RustbookSrc {
                     target: self.target,
                     name: INTERNER.intern_str($book_name),
-                    src: doc_src(builder),
+                    src: INTERNER.intern_path(builder.src.join($path)),
                 })
             }
         }
@@ -60,6 +60,7 @@
 // NOTE: When adding a book here, make sure to ALSO build the book by
 // adding a build step in `src/bootstrap/builder.rs`!
 book!(
+    CargoBook, "src/tools/cargo/src/doc", "cargo";
     EditionGuide, "src/doc/edition-guide", "edition-guide";
     EmbeddedBook, "src/doc/embedded-book", "embedded-book";
     Nomicon, "src/doc/nomicon", "nomicon";
@@ -69,10 +70,6 @@
     RustdocBook, "src/doc/rustdoc", "rustdoc";
 );
 
-fn doc_src(builder: &Builder<'_>) -> Interned<PathBuf> {
-    INTERNER.intern_path(builder.src.join("src/doc"))
-}
-
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct UnstableBook {
     target: Interned<String>,
@@ -96,49 +93,12 @@
         builder.ensure(RustbookSrc {
             target: self.target,
             name: INTERNER.intern_str("unstable-book"),
-            src: builder.md_doc_out(self.target),
+            src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
         })
     }
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct CargoBook {
-    target: Interned<String>,
-    name: Interned<String>,
-}
-
-impl Step for CargoBook {
-    type Output = ();
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let builder = run.builder;
-        run.path("src/tools/cargo/src/doc/book").default_condition(builder.config.docs)
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(CargoBook { target: run.target, name: INTERNER.intern_str("cargo") });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        let target = self.target;
-        let name = self.name;
-        let src = builder.src.join("src/tools/cargo/src/doc");
-
-        let out = builder.doc_out(target);
-        t!(fs::create_dir_all(&out));
-
-        let out = out.join(name);
-
-        builder.info(&format!("Cargo Book ({}) - {}", target, name));
-
-        let _ = fs::remove_dir_all(&out);
-
-        builder.run(builder.tool_cmd(Tool::Rustbook).arg("build").arg(&src).arg("-d").arg(out));
-    }
-}
-
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 struct RustbookSrc {
     target: Interned<String>,
     name: Interned<String>,
@@ -164,7 +124,6 @@
         t!(fs::create_dir_all(&out));
 
         let out = out.join(name);
-        let src = src.join(name);
         let index = out.join("index.html");
         let rustbook = builder.tool_exe(Tool::Rustbook);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
@@ -182,7 +141,6 @@
 pub struct TheBook {
     compiler: Compiler,
     target: Interned<String>,
-    name: &'static str,
 }
 
 impl Step for TheBook {
@@ -198,7 +156,6 @@
         run.builder.ensure(TheBook {
             compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
             target: run.target,
-            name: "book",
         });
     }
 
@@ -206,45 +163,30 @@
     ///
     /// We need to build:
     ///
-    /// * Book (first edition)
-    /// * Book (second edition)
+    /// * Book
+    /// * Older edition redirects
     /// * Version info and CSS
     /// * Index page
     /// * Redirect pages
     fn run(self, builder: &Builder<'_>) {
         let compiler = self.compiler;
         let target = self.target;
-        let name = self.name;
 
         // build book
         builder.ensure(RustbookSrc {
             target,
-            name: INTERNER.intern_string(name.to_string()),
-            src: doc_src(builder),
+            name: INTERNER.intern_str("book"),
+            src: INTERNER.intern_path(builder.src.join("src/doc/book")),
         });
 
         // building older edition redirects
-
-        let source_name = format!("{}/first-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
-
-        let source_name = format!("{}/second-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
-
-        let source_name = format!("{}/2018-edition", name);
-        builder.ensure(RustbookSrc {
-            target,
-            name: INTERNER.intern_string(source_name),
-            src: doc_src(builder),
-        });
+        for edition in &["first-edition", "second-edition", "2018-edition"] {
+            builder.ensure(RustbookSrc {
+                target,
+                name: INTERNER.intern_string(format!("book/{}", edition)),
+                src: INTERNER.intern_path(builder.src.join("src/doc/book").join(edition)),
+            });
+        }
 
         // build the version info page and CSS
         builder.ensure(Standalone { compiler, target });
@@ -449,7 +391,7 @@
 
         let run_cargo_rustdoc_for = |package: &str| {
             let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc");
-            compile::std_cargo(builder, &compiler, target, &mut cargo);
+            compile::std_cargo(builder, target, &mut cargo);
 
             // Keep a whitelist so we do not build internal stdlib crates, these will be
             // build by the rustc step later if enabled.
@@ -531,7 +473,7 @@
 
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
-        cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden");
+        cargo.env("RUSTDOCFLAGS", "--document-private-items");
         compile::rustc_cargo(builder, &mut cargo, target);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index ffc2436..2101ef2 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -38,6 +38,8 @@
     //
     // true => deny, false => warn
     pub deny_warnings: Option<bool>,
+
+    pub llvm_skip_rebuild: Option<bool>,
 }
 
 pub enum Subcommand {
@@ -102,7 +104,7 @@
 Subcommands:
     build       Compile either the compiler or libraries
     check       Compile either the compiler or libraries, using cargo check
-    clippy      Run clippy
+    clippy      Run clippy (uses rustup/cargo-installed clippy binary)
     fix         Run cargo fix
     fmt         Run rustfmt
     test        Build and run some test suites
@@ -150,6 +152,14 @@
             "VALUE",
         );
         opts.optopt("", "error-format", "rustc error format", "FORMAT");
+        opts.optopt(
+            "",
+            "llvm-skip-rebuild",
+            "whether rebuilding llvm should be skipped \
+             a VALUE of TRUE indicates that llvm will not be rebuilt \
+             VALUE overrides the skip-rebuild option in config.toml.",
+            "VALUE",
+        );
 
         // fn usage()
         let usage =
@@ -487,6 +497,9 @@
                 .map(|p| p.into())
                 .collect::<Vec<_>>(),
             deny_warnings: parse_deny_warnings(&matches),
+            llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map(
+                |s| s.parse::<bool>().expect("`llvm-skip-rebuild` should be either true or false"),
+            ),
         }
     }
 }
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 65b654f..6e5e3fe 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -20,7 +20,15 @@
     cmd.arg(&path);
     let cmd_debug = format!("{:?}", cmd);
     let status = cmd.status().expect("executing rustfmt");
-    assert!(status.success(), "running {} successful", cmd_debug);
+    if !status.success() {
+        eprintln!(
+            "Running `{}` failed.\nIf you're running `tidy`, \
+            try again with `--bless` flag. Or, you just want to format \
+            code, run `./x.py fmt` instead.",
+            cmd_debug,
+        );
+        std::process::exit(1);
+    }
 }
 
 #[derive(serde::Deserialize)]
diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs
index 57153e2..efeb865 100644
--- a/src/bootstrap/job.rs
+++ b/src/bootstrap/job.rs
@@ -35,84 +35,16 @@
 use std::mem;
 use std::ptr;
 
-type HANDLE = *mut u8;
-type BOOL = i32;
-type DWORD = u32;
-type LPHANDLE = *mut HANDLE;
-type LPVOID = *mut u8;
-type JOBOBJECTINFOCLASS = i32;
-type SIZE_T = usize;
-type LARGE_INTEGER = i64;
-type UINT = u32;
-type ULONG_PTR = usize;
-type ULONGLONG = u64;
-
-const FALSE: BOOL = 0;
-const DUPLICATE_SAME_ACCESS: DWORD = 0x2;
-const PROCESS_DUP_HANDLE: DWORD = 0x40;
-const JobObjectExtendedLimitInformation: JOBOBJECTINFOCLASS = 9;
-const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: DWORD = 0x2000;
-const JOB_OBJECT_LIMIT_PRIORITY_CLASS: DWORD = 0x00000020;
-const SEM_FAILCRITICALERRORS: UINT = 0x0001;
-const SEM_NOGPFAULTERRORBOX: UINT = 0x0002;
-const BELOW_NORMAL_PRIORITY_CLASS: DWORD = 0x00004000;
-
-extern "system" {
-    fn CreateJobObjectW(lpJobAttributes: *mut u8, lpName: *const u8) -> HANDLE;
-    fn CloseHandle(hObject: HANDLE) -> BOOL;
-    fn GetCurrentProcess() -> HANDLE;
-    fn OpenProcess(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE;
-    fn DuplicateHandle(
-        hSourceProcessHandle: HANDLE,
-        hSourceHandle: HANDLE,
-        hTargetProcessHandle: HANDLE,
-        lpTargetHandle: LPHANDLE,
-        dwDesiredAccess: DWORD,
-        bInheritHandle: BOOL,
-        dwOptions: DWORD,
-    ) -> BOOL;
-    fn AssignProcessToJobObject(hJob: HANDLE, hProcess: HANDLE) -> BOOL;
-    fn SetInformationJobObject(
-        hJob: HANDLE,
-        JobObjectInformationClass: JOBOBJECTINFOCLASS,
-        lpJobObjectInformation: LPVOID,
-        cbJobObjectInformationLength: DWORD,
-    ) -> BOOL;
-    fn SetErrorMode(mode: UINT) -> UINT;
-}
-
-#[repr(C)]
-struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
-    BasicLimitInformation: JOBOBJECT_BASIC_LIMIT_INFORMATION,
-    IoInfo: IO_COUNTERS,
-    ProcessMemoryLimit: SIZE_T,
-    JobMemoryLimit: SIZE_T,
-    PeakProcessMemoryUsed: SIZE_T,
-    PeakJobMemoryUsed: SIZE_T,
-}
-
-#[repr(C)]
-struct IO_COUNTERS {
-    ReadOperationCount: ULONGLONG,
-    WriteOperationCount: ULONGLONG,
-    OtherOperationCount: ULONGLONG,
-    ReadTransferCount: ULONGLONG,
-    WriteTransferCount: ULONGLONG,
-    OtherTransferCount: ULONGLONG,
-}
-
-#[repr(C)]
-struct JOBOBJECT_BASIC_LIMIT_INFORMATION {
-    PerProcessUserTimeLimit: LARGE_INTEGER,
-    PerJobUserTimeLimit: LARGE_INTEGER,
-    LimitFlags: DWORD,
-    MinimumWorkingsetSize: SIZE_T,
-    MaximumWorkingsetSize: SIZE_T,
-    ActiveProcessLimit: DWORD,
-    Affinity: ULONG_PTR,
-    PriorityClass: DWORD,
-    SchedulingClass: DWORD,
-}
+use winapi::shared::minwindef::{DWORD, FALSE, LPVOID};
+use winapi::um::errhandlingapi::SetErrorMode;
+use winapi::um::handleapi::{CloseHandle, DuplicateHandle};
+use winapi::um::jobapi2::{AssignProcessToJobObject, CreateJobObjectW, SetInformationJobObject};
+use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcess};
+use winapi::um::winbase::{BELOW_NORMAL_PRIORITY_CLASS, SEM_NOGPFAULTERRORBOX};
+use winapi::um::winnt::{
+    JobObjectExtendedLimitInformation, DUPLICATE_SAME_ACCESS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
+    JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
+};
 
 pub unsafe fn setup(build: &mut Build) {
     // Enable the Windows Error Reporting dialog which msys disables,
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 2a4e990..5bbd9f47 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -230,6 +230,8 @@
                 cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
             } else if target.contains("freebsd") {
                 cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
+            } else if target.contains("windows") {
+                cfg.define("CMAKE_SYSTEM_NAME", "Windows");
             }
 
             cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build"));
@@ -546,3 +548,136 @@
             .compile("rust_test_helpers");
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Sanitizers {
+    pub target: Interned<String>,
+}
+
+impl Step for Sanitizers {
+    type Output = Vec<SanitizerRuntime>;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/llvm-project/compiler-rt").path("src/sanitizers")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Sanitizers { target: run.target });
+    }
+
+    /// Builds sanitizer runtime libraries.
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let compiler_rt_dir = builder.src.join("src/llvm-project/compiler-rt");
+        if !compiler_rt_dir.exists() {
+            return Vec::new();
+        }
+
+        let out_dir = builder.native_dir(self.target).join("sanitizers");
+        let runtimes = supported_sanitizers(&out_dir, self.target);
+        if runtimes.is_empty() {
+            return runtimes;
+        }
+
+        let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+        if builder.config.dry_run {
+            return runtimes;
+        }
+
+        let done_stamp = out_dir.join("sanitizers-finished-building");
+        if done_stamp.exists() {
+            builder.info(&format!(
+                "Assuming that sanitizers rebuild is not necessary. \
+                To force a rebuild, remove the file `{}`",
+                done_stamp.display()
+            ));
+            return runtimes;
+        }
+
+        builder.info(&format!("Building sanitizers for {}", self.target));
+        let _time = util::timeit(&builder);
+
+        let mut cfg = cmake::Config::new(&compiler_rt_dir);
+        cfg.target(&self.target);
+        cfg.host(&builder.config.build);
+        cfg.profile("Release");
+
+        cfg.define("CMAKE_C_COMPILER_TARGET", self.target);
+        cfg.define("COMPILER_RT_BUILD_BUILTINS", "OFF");
+        cfg.define("COMPILER_RT_BUILD_CRT", "OFF");
+        cfg.define("COMPILER_RT_BUILD_LIBFUZZER", "OFF");
+        cfg.define("COMPILER_RT_BUILD_PROFILE", "OFF");
+        cfg.define("COMPILER_RT_BUILD_SANITIZERS", "ON");
+        cfg.define("COMPILER_RT_BUILD_XRAY", "OFF");
+        cfg.define("COMPILER_RT_DEFAULT_TARGET_ONLY", "ON");
+        cfg.define("COMPILER_RT_USE_LIBCXX", "OFF");
+        cfg.define("LLVM_CONFIG_PATH", &llvm_config);
+
+        t!(fs::create_dir_all(&out_dir));
+        cfg.out_dir(out_dir);
+
+        for runtime in &runtimes {
+            cfg.build_target(&runtime.cmake_target);
+            cfg.build();
+        }
+
+        t!(fs::write(&done_stamp, b""));
+
+        runtimes
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct SanitizerRuntime {
+    /// CMake target used to build the runtime.
+    pub cmake_target: String,
+    /// Path to the built runtime library.
+    pub path: PathBuf,
+    /// Library filename that will be used rustc.
+    pub name: String,
+}
+
+/// Returns sanitizers available on a given target.
+fn supported_sanitizers(out_dir: &Path, target: Interned<String>) -> Vec<SanitizerRuntime> {
+    let mut result = Vec::new();
+    match &*target {
+        "x86_64-apple-darwin" => {
+            for s in &["asan", "lsan", "tsan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}_osx_dynamic", s),
+                    path: out_dir
+                        .join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)),
+                    name: format!("librustc_rt.{}.dylib", s),
+                });
+            }
+        }
+        "x86_64-unknown-linux-gnu" => {
+            for s in &["asan", "lsan", "msan", "tsan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}-x86_64", s),
+                    path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)),
+                    name: format!("librustc_rt.{}.a", s),
+                });
+            }
+        }
+        "x86_64-fuchsia" => {
+            for s in &["asan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}-x86_64", s),
+                    path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-x86_64.a", s)),
+                    name: format!("librustc_rt.{}.a", s),
+                });
+            }
+        }
+        "aarch64-fuchsia" => {
+            for s in &["asan"] {
+                result.push(SanitizerRuntime {
+                    cmake_target: format!("clang_rt.{}-aarch64", s),
+                    path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-aarch64.a", s)),
+                    name: format!("librustc_rt.{}.a", s),
+                });
+            }
+        }
+        _ => {}
+    }
+    result
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index b5c8de0..a186c16 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -957,14 +957,6 @@
         }
 
         if suite == "debuginfo" {
-            let msvc = builder.config.build.contains("msvc");
-            if mode == "debuginfo" {
-                return builder.ensure(Compiletest {
-                    mode: if msvc { "debuginfo-cdb" } else { "debuginfo-gdb+lldb" },
-                    ..self
-                });
-            }
-
             builder
                 .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
         }
@@ -1659,7 +1651,7 @@
         let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
         match mode {
             Mode::Std => {
-                compile::std_cargo(builder, &compiler, target, &mut cargo);
+                compile::std_cargo(builder, target, &mut cargo);
             }
             Mode::Rustc => {
                 builder.ensure(compile::Rustc { compiler, target });
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 9fd2038..7f24768 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -289,8 +289,8 @@
 macro_rules! bootstrap_tool {
     ($(
         $name:ident, $path:expr, $tool_name:expr
-        $(,llvm_tools = $llvm:expr)*
         $(,is_external_tool = $external:expr)*
+        $(,is_unstable_tool = $unstable:expr)*
         $(,features = $features:expr)*
         ;
     )+) => {
@@ -301,15 +301,6 @@
             )+
         }
 
-        impl Tool {
-            /// Whether this tool requires LLVM to run
-            pub fn uses_llvm_tools(&self) -> bool {
-                match self {
-                    $(Tool::$name => false $(|| $llvm)*,)+
-                }
-            }
-        }
-
         impl<'a> Builder<'a> {
             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                 match tool {
@@ -350,7 +341,12 @@
                     compiler: self.compiler,
                     target: self.target,
                     tool: $tool_name,
-                    mode: Mode::ToolBootstrap,
+                    mode: if false $(|| $unstable)* {
+                        // use in-tree libraries for unstable features
+                        Mode::ToolStd
+                    } else {
+                        Mode::ToolBootstrap
+                    },
                     path: $path,
                     is_optional_tool: false,
                     source_type: if false $(|| $external)* {
@@ -377,7 +373,7 @@
     Tidy, "src/tools/tidy", "tidy";
     Linkchecker, "src/tools/linkchecker", "linkchecker";
     CargoTest, "src/tools/cargotest", "cargotest";
-    Compiletest, "src/tools/compiletest", "compiletest", llvm_tools = true;
+    Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true;
     BuildManifest, "src/tools/build-manifest", "build-manifest";
     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
     RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true;
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 5fd2598..7d1efe4 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -123,37 +123,24 @@
     // what can be found here:
     //
     // http://www.flexhex.com/docs/articles/hard-links.phtml
-    //
-    // Copied from std
     #[cfg(windows)]
-    #[allow(nonstandard_style)]
     fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
         use std::ffi::OsStr;
         use std::os::windows::ffi::OsStrExt;
         use std::ptr;
 
-        const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
-        const GENERIC_WRITE: DWORD = 0x40000000;
-        const OPEN_EXISTING: DWORD = 3;
-        const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
-        const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
-        const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
-        const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003;
-        const FILE_SHARE_DELETE: DWORD = 0x4;
-        const FILE_SHARE_READ: DWORD = 0x1;
-        const FILE_SHARE_WRITE: DWORD = 0x2;
+        use winapi::shared::minwindef::{DWORD, WORD};
+        use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
+        use winapi::um::handleapi::CloseHandle;
+        use winapi::um::ioapiset::DeviceIoControl;
+        use winapi::um::winbase::{FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT};
+        use winapi::um::winioctl::FSCTL_SET_REPARSE_POINT;
+        use winapi::um::winnt::{
+            FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_WRITE,
+            IO_REPARSE_TAG_MOUNT_POINT, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, WCHAR,
+        };
 
-        type BOOL = i32;
-        type DWORD = u32;
-        type HANDLE = *mut u8;
-        type LPCWSTR = *const u16;
-        type LPDWORD = *mut DWORD;
-        type LPOVERLAPPED = *mut u8;
-        type LPSECURITY_ATTRIBUTES = *mut u8;
-        type LPVOID = *mut u8;
-        type WCHAR = u16;
-        type WORD = u16;
-
+        #[allow(non_snake_case)]
         #[repr(C)]
         struct REPARSE_MOUNTPOINT_DATA_BUFFER {
             ReparseTag: DWORD,
@@ -165,29 +152,6 @@
             ReparseTarget: WCHAR,
         }
 
-        extern "system" {
-            fn CreateFileW(
-                lpFileName: LPCWSTR,
-                dwDesiredAccess: DWORD,
-                dwShareMode: DWORD,
-                lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
-                dwCreationDisposition: DWORD,
-                dwFlagsAndAttributes: DWORD,
-                hTemplateFile: HANDLE,
-            ) -> HANDLE;
-            fn DeviceIoControl(
-                hDevice: HANDLE,
-                dwIoControlCode: DWORD,
-                lpInBuffer: LPVOID,
-                nInBufferSize: DWORD,
-                lpOutBuffer: LPVOID,
-                nOutBufferSize: DWORD,
-                lpBytesReturned: LPDWORD,
-                lpOverlapped: LPOVERLAPPED,
-            ) -> BOOL;
-            fn CloseHandle(hObject: HANDLE) -> BOOL;
-        }
-
         fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
             Ok(s.as_ref().encode_wide().chain(Some(0)).collect())
         }
@@ -212,7 +176,7 @@
                 ptr::null_mut(),
             );
 
-            let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+            let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize];
             let db = data.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
             let buf = &mut (*db).ReparseTarget as *mut u16;
             let mut i = 0;
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 3f42533..43c3c57 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -1,7 +1,5 @@
-use std::fs::File;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
-use std::thread;
 use std::time::{SystemTime, UNIX_EPOCH};
 use std::{env, fs};
 
@@ -181,108 +179,6 @@
     }
 }
 
-#[must_use]
-pub struct NativeLibBoilerplate {
-    pub src_dir: PathBuf,
-    pub out_dir: PathBuf,
-}
-
-impl NativeLibBoilerplate {
-    /// On macOS we don't want to ship the exact filename that compiler-rt builds.
-    /// This conflicts with the system and ours is likely a wildly different
-    /// version, so they can't be substituted.
-    ///
-    /// As a result, we rename it here but we need to also use
-    /// `install_name_tool` on macOS to rename the commands listed inside of it to
-    /// ensure it's linked against correctly.
-    pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) {
-        if env::var("TARGET").unwrap() != "x86_64-apple-darwin" {
-            return;
-        }
-
-        let dir = self.out_dir.join("build/lib/darwin");
-        let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name);
-        let src = dir.join(&format!("lib{}.dylib", name));
-        let new_name = format!("lib__rustc__{}.dylib", name);
-        let dst = dir.join(&new_name);
-
-        println!("{} => {}", src.display(), dst.display());
-        fs::rename(&src, &dst).unwrap();
-        let status = Command::new("install_name_tool")
-            .arg("-id")
-            .arg(format!("@rpath/{}", new_name))
-            .arg(&dst)
-            .status()
-            .expect("failed to execute `install_name_tool`");
-        assert!(status.success());
-    }
-}
-
-impl Drop for NativeLibBoilerplate {
-    fn drop(&mut self) {
-        if !thread::panicking() {
-            t!(File::create(self.out_dir.join("rustbuild.timestamp")));
-        }
-    }
-}
-
-// Perform standard preparations for native libraries that are build only once for all stages.
-// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are
-// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler.
-// If Err is returned, then everything is up-to-date and further build actions can be skipped.
-// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
-// of scope, so all the build actions should be completed until then.
-pub fn native_lib_boilerplate(
-    src_dir: &Path,
-    out_name: &str,
-    link_name: &str,
-    search_subdir: &str,
-) -> Result<NativeLibBoilerplate, ()> {
-    rerun_if_changed_anything_in_dir(src_dir);
-
-    let out_dir =
-        env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| env::var_os("OUT_DIR").unwrap());
-    let out_dir = PathBuf::from(out_dir).join(out_name);
-    t!(fs::create_dir_all(&out_dir));
-    if link_name.contains('=') {
-        println!("cargo:rustc-link-lib={}", link_name);
-    } else {
-        println!("cargo:rustc-link-lib=static={}", link_name);
-    }
-    println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display());
-
-    let timestamp = out_dir.join("rustbuild.timestamp");
-    if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(src_dir, &timestamp) {
-        Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), out_dir })
-    } else {
-        Err(())
-    }
-}
-
-pub fn sanitizer_lib_boilerplate(
-    sanitizer_name: &str,
-) -> Result<(NativeLibBoilerplate, String), ()> {
-    let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() {
-        "x86_64-unknown-linux-gnu" => {
-            (format!("clang_rt.{}-x86_64", sanitizer_name), "build/lib/linux", false)
-        }
-        "x86_64-apple-darwin" => {
-            (format!("clang_rt.{}_osx_dynamic", sanitizer_name), "build/lib/darwin", true)
-        }
-        _ => return Err(()),
-    };
-    let to_link = if apple {
-        format!("dylib=__rustc__{}", link_name)
-    } else {
-        format!("static={}", link_name)
-    };
-    // This env var is provided by rustbuild to tell us where `compiler-rt`
-    // lives.
-    let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
-    let lib = native_lib_boilerplate(dir.as_ref(), sanitizer_name, &to_link, search_path)?;
-    Ok((lib, link_name))
-}
-
 fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
     t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
         let meta = t!(e.metadata());
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index 6bbf092..2a68a25 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -2,11 +2,24 @@
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
+  automake \
+  bison \
+  bzip2 \
+  flex \
+  help2man \
+  libtool-bin \
+  texinfo \
+  unzip \
+  wget \
+  xz-utils \
+  libncurses-dev \
+  gawk \
   make \
   file \
   curl \
   ca-certificates \
   python2.7 \
+  python3 \
   git \
   cmake \
   sudo \
@@ -35,6 +48,18 @@
     apt-get update && \
     apt-get install -y --no-install-recommends gcc-arm-embedded
 
+COPY scripts/rustbuild-setup.sh dist-various-1/build-riscv-toolchain.sh dist-various-1/riscv64-unknown-linux-gnu.config dist-various-1/crosstool-ng.sh /build/
+RUN ./crosstool-ng.sh
+
+# Crosstool-ng will refuse to build as root
+RUN sh ./rustbuild-setup.sh
+USER rustbuild
+
+RUN ./build-riscv-toolchain.sh
+
+USER root
+ENV PATH=/x-tools/riscv64-unknown-linux-gnu/bin:$PATH
+
 COPY dist-various-1/build-rumprun.sh /build
 RUN ./build-rumprun.sh
 
@@ -129,11 +154,13 @@
 ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv64gc-unknown-none-elf
+ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-gnu
 ENV TARGETS=$TARGETS,armebv7r-none-eabi
 ENV TARGETS=$TARGETS,armebv7r-none-eabihf
 ENV TARGETS=$TARGETS,armv7r-none-eabi
 ENV TARGETS=$TARGETS,armv7r-none-eabihf
 ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf
+ENV TARGETS=$TARGETS,armv7a-none-eabi
 
 # riscv targets currently do not need a C compiler, as compiler_builtins
 # doesn't currently have it enabled, and the riscv gcc compiler is not
@@ -147,6 +174,13 @@
     CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \
     AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \
     CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \
+    CC_armv7a_none_eabi=arm-none-eabi-gcc \
+    CC_armv7a_none_eabihf=arm-none-eabi-gcc \
+    CFLAGS_armv7a_none_eabi=-march=armv7-a \
+    CFLAGS_armv7a_none_eabihf=-march=armv7-a+vfpv3 \
+    CC_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-gcc \
+    AR_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-ar \
+    CXX_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-g++ \
     CC_riscv32i_unknown_none_elf=false \
     CC_riscv32imc_unknown_none_elf=false \
     CC_riscv32imac_unknown_none_elf=false \
diff --git a/src/ci/docker/dist-various-1/build-riscv-toolchain.sh b/src/ci/docker/dist-various-1/build-riscv-toolchain.sh
new file mode 100755
index 0000000..9cb5700
--- /dev/null
+++ b/src/ci/docker/dist-various-1/build-riscv-toolchain.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir -p /tmp/build-riscv
+cp riscv64-unknown-linux-gnu.config /tmp/build-riscv/.config
+cd /tmp/build-riscv
+hide_output ct-ng build
+cd ..
+rm -rf build-riscv
diff --git a/src/ci/docker/dist-various-1/crosstool-ng.sh b/src/ci/docker/dist-various-1/crosstool-ng.sh
new file mode 100755
index 0000000..b01fdd0
--- /dev/null
+++ b/src/ci/docker/dist-various-1/crosstool-ng.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -ex
+
+# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz
+url="https://ci-mirrors.rust-lang.org/rustc/crosstool-ng-1.24.0.tar.gz"
+curl -Lf $url | tar xzf -
+cd crosstool-ng-crosstool-ng-1.24.0
+./bootstrap
+./configure --prefix=/usr/local
+make -j$(nproc)
+make install
+cd ..
+rm -rf crosstool-ng-crosstool-ng-1.24.0
diff --git a/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config b/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config
new file mode 100644
index 0000000..dd06065
--- /dev/null
+++ b/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config
@@ -0,0 +1,908 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG  Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_dtc=y
+CT_CONFIGURE_has_svn=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+CT_EXPERIMENTAL=y
+# CT_ALLOW_BUILD_AS_ROOT is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+# CT_USE_MIRROR is not set
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+CT_PATCH_BUNDLED=y
+# CT_PATCH_LOCAL is not set
+# CT_PATCH_BUNDLED_LOCAL is not set
+# CT_PATCH_LOCAL_BUNDLED is not set
+# CT_PATCH_NONE is not set
+CT_PATCH_ORDER="bundled"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+# CT_LOG_EXTRA is not set
+CT_LOG_ALL=y
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="ALL"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+# CT_ARCH_MICROBLAZE is not set
+# CT_ARCH_MIPS is not set
+# CT_ARCH_MOXIE is not set
+# CT_ARCH_MSP430 is not set
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+CT_ARCH_RISCV=y
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="riscv"
+CT_ARCH_CHOICE_KSYM="RISCV"
+CT_ARCH_TUNE=""
+CT_ARCH_RISCV_SHOW=y
+
+#
+# Options for riscv
+#
+CT_ARCH_RISCV_PKG_KSYM=""
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+# CT_DEMULTILIB is not set
+CT_ARCH_SUPPORTS_BOTH_MMU=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=64
+# CT_ARCH_32 is not set
+CT_ARCH_64=y
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_ABI=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_ARCH="rv64gc"
+CT_ARCH_ABI=""
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+# CT_NATIVE is not set
+CT_CROSS=y
+# CT_CROSS_NATIVE is not set
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+# CT_LINUX_SRC_DEVEL is not set
+# CT_LINUX_SRC_CUSTOM is not set
+CT_LINUX_PATCH_GLOBAL=y
+# CT_LINUX_PATCH_BUNDLED is not set
+# CT_LINUX_PATCH_LOCAL is not set
+# CT_LINUX_PATCH_BUNDLED_LOCAL is not set
+# CT_LINUX_PATCH_LOCAL_BUNDLED is not set
+# CT_LINUX_PATCH_NONE is not set
+CT_LINUX_PATCH_ORDER="global"
+CT_LINUX_V_4_20=y
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+# CT_LINUX_V_4_4 is not set
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.20.8"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_later_than_4_8=y
+CT_LINUX_4_8_or_later=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_LINUX_REQUIRE_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+# CT_BINUTILS_SRC_DEVEL is not set
+# CT_BINUTILS_SRC_CUSTOM is not set
+CT_BINUTILS_PATCH_GLOBAL=y
+# CT_BINUTILS_PATCH_BUNDLED is not set
+# CT_BINUTILS_PATCH_LOCAL is not set
+# CT_BINUTILS_PATCH_BUNDLED_LOCAL is not set
+# CT_BINUTILS_PATCH_LOCAL_BUNDLED is not set
+# CT_BINUTILS_PATCH_NONE is not set
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_REQUIRE_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_MUSL is not set
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+# CT_GLIBC_SRC_DEVEL is not set
+# CT_GLIBC_SRC_CUSTOM is not set
+CT_GLIBC_PATCH_GLOBAL=y
+# CT_GLIBC_PATCH_BUNDLED is not set
+# CT_GLIBC_PATCH_LOCAL is not set
+# CT_GLIBC_PATCH_BUNDLED_LOCAL is not set
+# CT_GLIBC_PATCH_LOCAL_BUNDLED is not set
+# CT_GLIBC_PATCH_NONE is not set
+CT_GLIBC_PATCH_ORDER="global"
+CT_GLIBC_V_2_29=y
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.29"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_later=y
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_REQUIRE_2_29_or_later=y
+CT_GLIBC_later_than_2_27=y
+CT_GLIBC_2_27_or_later=y
+CT_GLIBC_later_than_2_26=y
+CT_GLIBC_2_26_or_later=y
+CT_GLIBC_later_than_2_25=y
+CT_GLIBC_2_25_or_later=y
+CT_GLIBC_later_than_2_24=y
+CT_GLIBC_2_24_or_later=y
+CT_GLIBC_later_than_2_23=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_BUILD_SSP=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_ENABLE_FORTIFIED_BUILD is not set
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+CT_GLIBC_KERNEL_VERSION_NONE=y
+# CT_GLIBC_KERNEL_VERSION_AS_HEADERS is not set
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL=""
+CT_GLIBC_SSP_DEFAULT=y
+# CT_GLIBC_SSP_NO is not set
+# CT_GLIBC_SSP_YES is not set
+# CT_GLIBC_SSP_ALL is not set
+# CT_GLIBC_SSP_STRONG is not set
+# CT_GLIBC_ENABLE_WERROR is not set
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+# CT_GCC_USE_LINARO is not set
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+# CT_GCC_SRC_DEVEL is not set
+# CT_GCC_SRC_CUSTOM is not set
+CT_GCC_PATCH_GLOBAL=y
+# CT_GCC_PATCH_BUNDLED is not set
+# CT_GCC_PATCH_LOCAL is not set
+# CT_GCC_PATCH_BUNDLED_LOCAL is not set
+# CT_GCC_PATCH_LOCAL_BUNDLED is not set
+# CT_GCC_PATCH_NONE is not set
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_REQUIRE_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_REQUIRE_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_REQUIRE_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+# CT_CC_LANG_ADA is not set
+# CT_CC_LANG_OBJC is not set
+# CT_CC_LANG_OBJCXX is not set
+# CT_CC_LANG_GOLANG is not set
+CT_CC_LANG_OTHERS=""
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+CT_DEBUG_GDB=y
+CT_DEBUG_GDB_PKG_KSYM="GDB"
+CT_GDB_DIR_NAME="gdb"
+CT_GDB_USE_GNU=y
+CT_GDB_USE="GDB"
+CT_GDB_PKG_NAME="gdb"
+CT_GDB_SRC_RELEASE=y
+# CT_GDB_SRC_DEVEL is not set
+# CT_GDB_SRC_CUSTOM is not set
+CT_GDB_PATCH_GLOBAL=y
+# CT_GDB_PATCH_BUNDLED is not set
+# CT_GDB_PATCH_LOCAL is not set
+# CT_GDB_PATCH_BUNDLED_LOCAL is not set
+# CT_GDB_PATCH_LOCAL_BUNDLED is not set
+# CT_GDB_PATCH_NONE is not set
+CT_GDB_PATCH_ORDER="global"
+CT_GDB_V_8_2=y
+# CT_GDB_V_8_1 is not set
+# CT_GDB_V_8_0 is not set
+# CT_GDB_NO_VERSIONS is not set
+CT_GDB_VERSION="8.2.1"
+CT_GDB_MIRRORS="$(CT_Mirrors GNU gdb) $(CT_Mirrors sourceware gdb/releases)"
+CT_GDB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GDB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GDB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GDB_SIGNATURE_FORMAT=""
+CT_GDB_later_than_8_0=y
+CT_GDB_8_0_or_later=y
+CT_GDB_REQUIRE_8_0_or_later=y
+CT_GDB_later_than_7_12=y
+CT_GDB_7_12_or_later=y
+CT_GDB_later_than_7_2=y
+CT_GDB_7_2_or_later=y
+CT_GDB_later_than_7_0=y
+CT_GDB_7_0_or_later=y
+CT_GDB_CROSS=y
+# CT_GDB_CROSS_STATIC is not set
+# CT_GDB_CROSS_SIM is not set
+# CT_GDB_CROSS_PYTHON is not set
+CT_GDB_CROSS_EXTRA_CONFIG_ARRAY=""
+# CT_GDB_NATIVE is not set
+# CT_GDB_GDBSERVER is not set
+CT_GDB_HAS_PKGVERSION_BUGURL=y
+CT_GDB_HAS_PYTHON=y
+CT_GDB_INSTALL_GDBINIT=y
+CT_GDB_HAS_IPA_LIB=y
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+CT_COMP_LIBS_EXPAT=y
+CT_COMP_LIBS_EXPAT_PKG_KSYM="EXPAT"
+CT_EXPAT_DIR_NAME="expat"
+CT_EXPAT_PKG_NAME="expat"
+CT_EXPAT_SRC_RELEASE=y
+# CT_EXPAT_SRC_DEVEL is not set
+# CT_EXPAT_SRC_CUSTOM is not set
+CT_EXPAT_PATCH_GLOBAL=y
+# CT_EXPAT_PATCH_BUNDLED is not set
+# CT_EXPAT_PATCH_LOCAL is not set
+# CT_EXPAT_PATCH_BUNDLED_LOCAL is not set
+# CT_EXPAT_PATCH_LOCAL_BUNDLED is not set
+# CT_EXPAT_PATCH_NONE is not set
+CT_EXPAT_PATCH_ORDER="global"
+CT_EXPAT_V_2_2=y
+# CT_EXPAT_NO_VERSIONS is not set
+CT_EXPAT_VERSION="2.2.6"
+CT_EXPAT_MIRRORS="http://downloads.sourceforge.net/project/expat/expat/${CT_EXPAT_VERSION}"
+CT_EXPAT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_EXPAT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_EXPAT_ARCHIVE_FORMATS=".tar.bz2"
+CT_EXPAT_SIGNATURE_FORMAT=""
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+# CT_GETTEXT_SRC_DEVEL is not set
+# CT_GETTEXT_SRC_CUSTOM is not set
+CT_GETTEXT_PATCH_GLOBAL=y
+# CT_GETTEXT_PATCH_BUNDLED is not set
+# CT_GETTEXT_PATCH_LOCAL is not set
+# CT_GETTEXT_PATCH_BUNDLED_LOCAL is not set
+# CT_GETTEXT_PATCH_LOCAL_BUNDLED is not set
+# CT_GETTEXT_PATCH_NONE is not set
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+# CT_GMP_SRC_DEVEL is not set
+# CT_GMP_SRC_CUSTOM is not set
+CT_GMP_PATCH_GLOBAL=y
+# CT_GMP_PATCH_BUNDLED is not set
+# CT_GMP_PATCH_LOCAL is not set
+# CT_GMP_PATCH_BUNDLED_LOCAL is not set
+# CT_GMP_PATCH_LOCAL_BUNDLED is not set
+# CT_GMP_PATCH_NONE is not set
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+# CT_ISL_SRC_DEVEL is not set
+# CT_ISL_SRC_CUSTOM is not set
+CT_ISL_PATCH_GLOBAL=y
+# CT_ISL_PATCH_BUNDLED is not set
+# CT_ISL_PATCH_LOCAL is not set
+# CT_ISL_PATCH_BUNDLED_LOCAL is not set
+# CT_ISL_PATCH_LOCAL_BUNDLED is not set
+# CT_ISL_PATCH_NONE is not set
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+# CT_LIBICONV_SRC_DEVEL is not set
+# CT_LIBICONV_SRC_CUSTOM is not set
+CT_LIBICONV_PATCH_GLOBAL=y
+# CT_LIBICONV_PATCH_BUNDLED is not set
+# CT_LIBICONV_PATCH_LOCAL is not set
+# CT_LIBICONV_PATCH_BUNDLED_LOCAL is not set
+# CT_LIBICONV_PATCH_LOCAL_BUNDLED is not set
+# CT_LIBICONV_PATCH_NONE is not set
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+# CT_MPC_SRC_DEVEL is not set
+# CT_MPC_SRC_CUSTOM is not set
+CT_MPC_PATCH_GLOBAL=y
+# CT_MPC_PATCH_BUNDLED is not set
+# CT_MPC_PATCH_LOCAL is not set
+# CT_MPC_PATCH_BUNDLED_LOCAL is not set
+# CT_MPC_PATCH_LOCAL_BUNDLED is not set
+# CT_MPC_PATCH_NONE is not set
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+# CT_MPFR_SRC_DEVEL is not set
+# CT_MPFR_SRC_CUSTOM is not set
+CT_MPFR_PATCH_GLOBAL=y
+# CT_MPFR_PATCH_BUNDLED is not set
+# CT_MPFR_PATCH_LOCAL is not set
+# CT_MPFR_PATCH_BUNDLED_LOCAL is not set
+# CT_MPFR_PATCH_LOCAL_BUNDLED is not set
+# CT_MPFR_PATCH_NONE is not set
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+# CT_NCURSES_SRC_DEVEL is not set
+# CT_NCURSES_SRC_CUSTOM is not set
+CT_NCURSES_PATCH_GLOBAL=y
+# CT_NCURSES_PATCH_BUNDLED is not set
+# CT_NCURSES_PATCH_LOCAL is not set
+# CT_NCURSES_PATCH_BUNDLED_LOCAL is not set
+# CT_NCURSES_PATCH_LOCAL_BUNDLED is not set
+# CT_NCURSES_PATCH_NONE is not set
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+# CT_NCURSES_NEW_ABI is not set
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+# CT_ZLIB_SRC_DEVEL is not set
+# CT_ZLIB_SRC_CUSTOM is not set
+CT_ZLIB_PATCH_GLOBAL=y
+# CT_ZLIB_PATCH_BUNDLED is not set
+# CT_ZLIB_PATCH_LOCAL is not set
+# CT_ZLIB_PATCH_BUNDLED_LOCAL is not set
+# CT_ZLIB_PATCH_LOCAL_BUNDLED is not set
+# CT_ZLIB_PATCH_NONE is not set
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_EXPAT_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_EXPAT=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
+
+#
+# Test suite
+#
+# CT_TEST_SUITE_GCC is not set
diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
index 925d5ca..b868677 100755
--- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
@@ -12,7 +12,7 @@
 git clone https://github.com/CraneStation/wasi-libc
 
 cd wasi-libc
-git reset --hard f645f498dfbbbc00a7a97874d33082d3605c3f21
+git reset --hard 1fad33890a5e299027ce0eab7b6ad5260585e347
 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
 
 cd ..
diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile
index b2748d9..890e132 100644
--- a/src/ci/docker/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:19.04
+FROM ubuntu:19.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile
index 4ec4364..b864c09 100644
--- a/src/ci/docker/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/x86_64-gnu/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:19.04
+FROM ubuntu:19.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh
index fb82847..7c43d03 100755
--- a/src/ci/publish_toolstate.sh
+++ b/src/ci/publish_toolstate.sh
@@ -3,7 +3,7 @@
 set -euo pipefail
 IFS=$'\n\t'
 
-source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
+source "$(cd "$(dirname "$0")" && pwd)/shared.sh"
 
 # The following lines are also found in src/bootstrap/toolstate.rs,
 # so if updating here, please also update that file.
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index 0bfd7ff..206065d 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -80,7 +80,7 @@
 
 function ciCheckoutPath {
     if isAzurePipelines; then
-        echo "${SYSTEM_WORKFOLDER}"
+        echo "${BUILD_SOURCESDIRECTORY}"
     elif isGitHubActions; then
         echo "${GITHUB_WORKSPACE}"
     else
diff --git a/src/doc/book b/src/doc/book
index 5c5cfd2..87dd684 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 5c5cfd2e94cd42632798d9bd3d1116133e128ac9
+Subproject commit 87dd6843678575f8dda962f239d14ef4be14b352
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index 9493b7d..4d78994 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit 9493b7d4dc97eda439bd8780f05ad7b234cd1cd7
+Subproject commit 4d78994915af1bde9a95c04a8c27d8dca066232a
diff --git a/src/doc/reference b/src/doc/reference
index e115753..11e893f 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit e1157538e86d83df0cf95d5e33bd943f80d0248f
+Subproject commit 11e893fc1357bc688418ddf1087c2b7aa25d154d
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 1d59403..1c2bd02 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 1d59403cb5269c190cc52a95584ecc280345495a
+Subproject commit 1c2bd024d13f8011307e13386cf1fea2180352b5
diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide
index b5c6bab..92baf72 160000
--- a/src/doc/rustc-guide
+++ b/src/doc/rustc-guide
@@ -1 +1 @@
-Subproject commit b5c6babcdd4ce1fa90458b7827a5fde082e79e87
+Subproject commit 92baf7293dd2d418d2ac4b141b0faa822075d9f7
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
new file mode 100644
index 0000000..cbb90bd
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -0,0 +1,163 @@
+# `sanitizer`
+
+The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699).
+
+------------------------
+
+This feature allows for use of one of following sanitizers:
+
+* [AddressSanitizer][clang-asan] a faster memory error detector. Can
+  detect out-of-bounds access to heap, stack, and globals, use after free, use
+  after return, double free, invalid free, memory leaks.
+* [LeakSanitizer][clang-lsan] a run-time memory leak detector.
+* [MemorySanitizer][clang-msan] a detector of uninitialized reads.
+* [ThreadSanitizer][clang-tsan] a fast data race detector.
+
+To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one
+of `address`, `leak`, `memory` or `thread`.
+
+# Examples
+
+This sections show various issues that can be detected with sanitizers.  For
+simplicity, the examples are prepared under assumption that optimization level
+used is zero.
+
+## AddressSanitizer
+
+Stack buffer overflow:
+
+```shell
+$ cat a.rs
+fn main() {
+    let xs = [0, 1, 2, 3];
+    let _y = unsafe { *xs.as_ptr().offset(4) };
+}
+$ rustc -Zsanitizer=address a.rs
+$ ./a
+=================================================================
+==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388
+READ of size 4 at 0x7ffcc15f43d0 thread T0
+    #0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4)
+    #1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb)
+    #2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12
+    #3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39
+    #4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7
+    #5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12
+    #6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8
+    #7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24
+    #8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61)
+    #9 0x55f77dc0163a in main (/tmp/a+0xa63a)
+    #10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
+    #11 0x55f77dc01289 in _start (/tmp/a+0xa289)
+
+Address 0x7ffcc15f43d0 is located in stack of thread T0 at offset 48 in frame
+    #0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f)
+
+  This frame has 1 object(s):
+    [32, 48) 'xs' <== Memory access at offset 48 overflows this variable
+HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
+      (longjmp and C++ exceptions *are* supported)
+SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4) in a::main::hab3bd2a745c2d0ac
+Shadow bytes around the buggy address:
+  0x1000182b6820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6860: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=>0x1000182b6870: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
+  0x1000182b6880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b6890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+  0x1000182b68c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Shadow byte legend (one shadow byte represents 8 application bytes):
+  Addressable:           00
+  Partially addressable: 01 02 03 04 05 06 07 
+  Heap left redzone:       fa
+  Freed heap region:       fd
+  Stack left redzone:      f1
+  Stack mid redzone:       f2
+  Stack right redzone:     f3
+  Stack after return:      f5
+  Stack use after scope:   f8
+  Global redzone:          f9
+  Global init order:       f6
+  Poisoned by user:        f7
+  Container overflow:      fc
+  Array cookie:            ac
+  Intra object redzone:    bb
+  ASan internal:           fe
+  Left alloca redzone:     ca
+  Right alloca redzone:    cb
+  Shadow gap:              cc
+==10029==ABORTING
+```
+
+## MemorySanitizer
+
+Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument
+standard library, and passing `-msan-track-origins=2` to the LLVM to track
+origins of uninitialized memory:
+
+```shell
+$ cat src/main.rs
+use std::mem::MaybeUninit;
+
+fn main() {
+    unsafe {
+        let a = MaybeUninit::<[usize; 4]>::uninit();
+        let a = a.assume_init();
+        println!("{}", a[2]);
+    }
+}
+
+$ env RUSTFLAGS="-Zsanitizer=memory -Cllvm-args=-msan-track-origins=2" cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
+==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
+    #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
+...
+  Uninitialized value was stored to memory at
+    #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3
+    #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16
+
+  Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E'
+    #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
+```
+
+
+# Instrumentation of external dependencies and std
+
+The sanitizers to varying degrees work correctly with partially instrumented
+code. On the one extreme is LeakSanitizer that doesn't use any compile time
+instrumentation, on the other is MemorySanitizer that requires that all program
+code to be instrumented (failing to achieve that will inevitably result in
+false positives).
+
+It is strongly recommended to combine sanitizers with recompiled and
+instrumented standard library, for example using [cargo `-Zbuild-std`
+functionality][build-std].
+
+[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+
+# Build scripts and procedural macros
+
+Use of sanitizers together with build scripts and procedural macros is
+technically possible, but in almost all cases it would be best avoided.  This
+is especially true for procedural macros which would require an instrumented
+version of rustc.
+
+In more practical terms when using cargo always remember to pass `--target`
+flag, so that rustflags will not be applied to build scripts and procedural
+macros.
+
+# Additional Information
+
+* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
+* [AddressSanitizer in Clang][clang-asan]
+* [LeakSanitizer in Clang][clang-lsan]
+* [MemorySanitizer in Clang][clang-msan]
+* [ThreadSanitizer in Clang][clang-tsan]
+
+[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
+[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
+[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
+[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
diff --git a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md
index 6187f39..53e0109 100644
--- a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md
+++ b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md
@@ -1,8 +1,8 @@
 # `infer_static_outlives_requirements`
 
-The tracking issue for this feature is: [#44493]
+The tracking issue for this feature is: [#54185]
 
-[#44493]: https://github.com/rust-lang/rust/issues/44493
+[#54185]: https://github.com/rust-lang/rust/issues/54185
 
 ------------------------
 The `infer_static_outlives_requirements` feature indicates that certain
diff --git a/src/doc/unstable-book/src/language-features/member-constraints.md b/src/doc/unstable-book/src/language-features/member-constraints.md
index 0d11c31..3ba4a3e 100644
--- a/src/doc/unstable-book/src/language-features/member-constraints.md
+++ b/src/doc/unstable-book/src/language-features/member-constraints.md
@@ -1,8 +1,8 @@
 # `member_constraints`
 
-The tracking issue for this feature is: [#61977]
+The tracking issue for this feature is: [#61997]
 
-[#61977]: https://github.com/rust-lang/rust/issues/61977
+[#61997]: https://github.com/rust-lang/rust/issues/61997
 
 ------------------------
 
diff --git a/src/doc/unstable-book/src/language-features/repr128.md b/src/doc/unstable-book/src/language-features/repr128.md
index 0858988..146f50e 100644
--- a/src/doc/unstable-book/src/language-features/repr128.md
+++ b/src/doc/unstable-book/src/language-features/repr128.md
@@ -1,8 +1,8 @@
 # `repr128`
 
-The tracking issue for this feature is: [#35118]
+The tracking issue for this feature is: [#56071]
 
-[#35118]: https://github.com/rust-lang/rust/issues/35118
+[#56071]: https://github.com/rust-lang/rust/issues/56071
 
 ------------------------
 
diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md
deleted file mode 100644
index cdb7449..0000000
--- a/src/doc/unstable-book/src/language-features/slice-patterns.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# `slice_patterns`
-
-The tracking issue for this feature is: [#62254]
-
-[#62254]: https://github.com/rust-lang/rust/issues/62254
-
-------------------------
-
-The `slice_patterns` feature gate lets you use `..` to indicate any number of
-elements inside a pattern matching a slice. This wildcard can only be used once
-for a given array. If there's an pattern before the `..`, the subslice will be
-matched against that pattern. For example:
-
-```rust
-#![feature(slice_patterns)]
-
-fn is_symmetric(list: &[u32]) -> bool {
-    match list {
-        &[] | &[_] => true,
-        &[x, ref inside @ .., y] if x == y => is_symmetric(inside),
-        &[..] => false,
-    }
-}
-
-fn main() {
-    let sym = &[0, 1, 4, 2, 4, 1, 0];
-    assert!(is_symmetric(sym));
-
-    let not_sym = &[0, 1, 7, 2, 4, 1, 0];
-    assert!(!is_symmetric(not_sym));
-}
-```
diff --git a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
deleted file mode 100644
index 82ae67f..0000000
--- a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `sanitizer_runtime_lib`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/liballoc/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs
index eb5f51d..ea69769 100644
--- a/src/liballoc/benches/btree/map.rs
+++ b/src/liballoc/benches/btree/map.rs
@@ -146,6 +146,36 @@
     bench_iter(b, 100000);
 }
 
+fn bench_iter_mut(b: &mut Bencher, size: i32) {
+    let mut map = BTreeMap::<i32, i32>::new();
+    let mut rng = thread_rng();
+
+    for _ in 0..size {
+        map.insert(rng.gen(), rng.gen());
+    }
+
+    b.iter(|| {
+        for kv in map.iter_mut() {
+            black_box(kv);
+        }
+    });
+}
+
+#[bench]
+pub fn iter_mut_20(b: &mut Bencher) {
+    bench_iter_mut(b, 20);
+}
+
+#[bench]
+pub fn iter_mut_1000(b: &mut Bencher) {
+    bench_iter_mut(b, 1000);
+}
+
+#[bench]
+pub fn iter_mut_100000(b: &mut Bencher) {
+    bench_iter_mut(b, 100000);
+}
+
 fn bench_first_and_last(b: &mut Bencher, size: i32) {
     let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
     b.iter(|| {
diff --git a/src/liballoc/benches/btree/set.rs b/src/liballoc/benches/btree/set.rs
index 18502de..d7c1d95 100644
--- a/src/liballoc/benches/btree/set.rs
+++ b/src/liballoc/benches/btree/set.rs
@@ -14,19 +14,13 @@
 }
 
 fn neg(n: usize) -> BTreeSet<i32> {
-    let mut set = BTreeSet::new();
-    for i in -(n as i32)..=-1 {
-        set.insert(i);
-    }
+    let set: BTreeSet<i32> = (-(n as i32)..=-1).collect();
     assert_eq!(set.len(), n);
     set
 }
 
 fn pos(n: usize) -> BTreeSet<i32> {
-    let mut set = BTreeSet::new();
-    for i in 1..=(n as i32) {
-        set.insert(i);
-    }
+    let set: BTreeSet<i32> = (1..=(n as i32)).collect();
     assert_eq!(set.len(), n);
     set
 }
@@ -56,6 +50,43 @@
     };
 }
 
+const BUILD_SET_SIZE: usize = 100;
+
+#[bench]
+pub fn build_and_clear(b: &mut Bencher) {
+    b.iter(|| pos(BUILD_SET_SIZE).clear())
+}
+
+#[bench]
+pub fn build_and_drop(b: &mut Bencher) {
+    b.iter(|| pos(BUILD_SET_SIZE))
+}
+
+#[bench]
+pub fn build_and_into_iter(b: &mut Bencher) {
+    b.iter(|| pos(BUILD_SET_SIZE).into_iter().count())
+}
+
+#[bench]
+pub fn build_and_pop_all(b: &mut Bencher) {
+    b.iter(|| {
+        let mut s = pos(BUILD_SET_SIZE);
+        while s.pop_first().is_some() {}
+        s
+    });
+}
+
+#[bench]
+pub fn build_and_remove_all(b: &mut Bencher) {
+    b.iter(|| {
+        let mut s = pos(BUILD_SET_SIZE);
+        while let Some(elt) = s.iter().copied().next() {
+            s.remove(&elt);
+        }
+        s
+    });
+}
+
 set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]}
 set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]}
 set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]}
diff --git a/src/liballoc/benches/string.rs b/src/liballoc/benches/string.rs
index 599c8b1..5c95160 100644
--- a/src/liballoc/benches/string.rs
+++ b/src/liballoc/benches/string.rs
@@ -1,5 +1,5 @@
 use std::iter::repeat;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_with_capacity(b: &mut Bencher) {
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index 302c2bc..e70f881 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -1968,7 +1968,7 @@
                 (i, false) => i,
             },
             (_, Unbounded) => 0,
-            (true, Included(_)) => min_node.keys().len(),
+            (true, Included(_)) => min_node.len(),
             (true, Excluded(_)) => 0,
         };
 
@@ -1987,9 +1987,9 @@
                 }
                 (i, false) => i,
             },
-            (_, Unbounded) => max_node.keys().len(),
+            (_, Unbounded) => max_node.len(),
             (true, Included(_)) => 0,
-            (true, Excluded(_)) => max_node.keys().len(),
+            (true, Excluded(_)) => max_node.len(),
         };
 
         if !diverged {
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index 260e51d..d9cdebb 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -54,10 +54,8 @@
 /// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
 /// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited
 /// by `as_header`.)
-/// See `into_key_slice` for an explanation of K2. K2 cannot be safely transmuted around
-/// because the size of `NodeHeader` depends on its alignment!
 #[repr(C)]
-struct NodeHeader<K, V, K2 = ()> {
+struct NodeHeader<K, V> {
     /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
     /// This either points to an actual node or is null.
     parent: *const InternalNode<K, V>,
@@ -72,9 +70,6 @@
     /// This next to `parent_idx` to encourage the compiler to join `len` and
     /// `parent_idx` into the same 32-bit word, reducing space overhead.
     len: u16,
-
-    /// See `into_key_slice`.
-    keys_start: [K2; 0],
 }
 #[repr(C)]
 struct LeafNode<K, V> {
@@ -128,7 +123,7 @@
 // We use just a header in order to save space, since no operation on an empty tree will
 // ever take a pointer past the first key.
 static EMPTY_ROOT_NODE: NodeHeader<(), ()> =
-    NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0, keys_start: [] };
+    NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 };
 
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
 /// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
@@ -390,8 +385,8 @@
     }
 
     /// Borrows a view into the keys stored in the node.
-    /// Works on all possible nodes, including the shared root.
-    pub fn keys(&self) -> &[K] {
+    /// The caller must ensure that the node is not the shared root.
+    pub unsafe fn keys(&self) -> &[K] {
         self.reborrow().into_key_slice()
     }
 
@@ -525,48 +520,11 @@
 }
 
 impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
-    fn into_key_slice(self) -> &'a [K] {
-        // We have to be careful here because we might be pointing to the shared root.
-        // In that case, we must not create an `&LeafNode`.  We could just return
-        // an empty slice whenever the length is 0 (this includes the shared root),
-        // but we want to avoid that run-time check.
-        // Instead, we create a slice pointing into the node whenever possible.
-        // We can sometimes do this even for the shared root, as the slice will be
-        // empty and `NodeHeader` contains an empty `keys_start` array.
-        // We cannot *always* do this because:
-        // - `keys_start` is not correctly typed because we want `NodeHeader`'s size to
-        //   not depend on the alignment of `K` (needed because `as_header` should be safe).
-        //   For this reason, `NodeHeader` has this `K2` parameter (that's usually `()`
-        //   and hence just adds a size-0-align-1 field, not affecting layout).
-        //   If the correctly typed header is more highly aligned than the allocated header,
-        //   we cannot transmute safely.
-        // - Even if we can transmute, the offset of a correctly typed `keys_start` might
-        //   be different and outside the bounds of the allocated header!
-        // So we do an alignment check and a size check first, that will be evaluated
-        // at compile-time, and only do any run-time check in the rare case that
-        // the compile-time checks signal danger.
-        if (mem::align_of::<NodeHeader<K, V, K>>() > mem::align_of::<NodeHeader<K, V>>()
-            || mem::size_of::<NodeHeader<K, V, K>>() != mem::size_of::<NodeHeader<K, V>>())
-            && self.is_shared_root()
-        {
-            &[]
-        } else {
-            // If we are a `LeafNode<K, V>`, we can always transmute to
-            // `NodeHeader<K, V, K>` and `keys_start` always has the same offset
-            // as the actual `keys`.
-            // Thanks to the checks above, we know that we can transmute to
-            // `NodeHeader<K, V, K>` and that `keys_start` will be
-            // in-bounds of some allocation even if this is the shared root!
-            // (We might be one-past-the-end, but that is allowed by LLVM.)
-            // Thus we can use `NodeHeader<K, V, K>`
-            // to compute the pointer where the keys start.
-            // This entire hack will become unnecessary once
-            // <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw
-            // pointer to the `keys` field of `*const InternalNode<K, V>`.
-            let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>;
-            let keys = unsafe { &(*header).keys_start as *const _ as *const K };
-            unsafe { slice::from_raw_parts(keys, self.len()) }
-        }
+    /// The caller must ensure that the node is not the shared root.
+    unsafe fn into_key_slice(self) -> &'a [K] {
+        debug_assert!(!self.is_shared_root());
+        // We cannot be the shared root, so `as_leaf` is okay.
+        slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
     }
 
     /// The caller must ensure that the node is not the shared root.
@@ -576,9 +534,10 @@
         unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
     }
 
+    /// The caller must ensure that the node is not the shared root.
     fn into_slices(self) -> (&'a [K], &'a [V]) {
         let k = unsafe { ptr::read(&self) };
-        (k.into_key_slice(), self.into_val_slice())
+        (unsafe { k.into_key_slice() }, self.into_val_slice())
     }
 }
 
@@ -589,20 +548,15 @@
         unsafe { &mut *(self.root as *mut Root<K, V>) }
     }
 
+    /// The caller must ensure that the node is not the shared root.
     fn into_key_slice_mut(mut self) -> &'a mut [K] {
-        // Same as for `into_key_slice` above, we try to avoid a run-time check.
-        if (mem::align_of::<NodeHeader<K, V, K>>() > mem::align_of::<NodeHeader<K, V>>()
-            || mem::size_of::<NodeHeader<K, V, K>>() != mem::size_of::<NodeHeader<K, V>>())
-            && self.is_shared_root()
-        {
-            &mut []
-        } else {
-            unsafe {
-                slice::from_raw_parts_mut(
-                    MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
-                    self.len(),
-                )
-            }
+        debug_assert!(!self.is_shared_root());
+        // We cannot be the shared root, so `as_leaf_mut` is okay.
+        unsafe {
+            slice::from_raw_parts_mut(
+                MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
+                self.len(),
+            )
         }
     }
 
diff --git a/src/liballoc/collections/btree/search.rs b/src/liballoc/collections/btree/search.rs
index 3f3c49a..579624c 100644
--- a/src/liballoc/collections/btree/search.rs
+++ b/src/liballoc/collections/btree/search.rs
@@ -46,6 +46,11 @@
     }
 }
 
+/// Returns the index in the node at which the key (or an equivalent) exists
+/// or could exist, and whether it exists in the node itself. If it doesn't
+/// exist in the node itself, it may exist in the subtree with that index
+/// (if the node has subtrees). If the key doesn't exist in node or subtree,
+/// the returned index is the position or subtree to insert at.
 pub fn search_linear<BorrowType, K, V, Type, Q: ?Sized>(
     node: &NodeRef<BorrowType, K, V, Type>,
     key: &Q,
@@ -54,12 +59,20 @@
     Q: Ord,
     K: Borrow<Q>,
 {
-    for (i, k) in node.keys().iter().enumerate() {
-        match key.cmp(k.borrow()) {
-            Ordering::Greater => {}
-            Ordering::Equal => return (i, true),
-            Ordering::Less => return (i, false),
+    // This function is defined over all borrow types (immutable, mutable, owned),
+    // and may be called on the shared root in each case.
+    // Using `keys()` is fine here even if BorrowType is mutable, as all we return
+    // is an index -- not a reference.
+    let len = node.len();
+    if len > 0 {
+        let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root
+        for (i, k) in keys.iter().enumerate() {
+            match key.cmp(k.borrow()) {
+                Ordering::Greater => {}
+                Ordering::Equal => return (i, true),
+                Ordering::Less => return (i, false),
+            }
         }
     }
-    (node.keys().len(), false)
+    (len, false)
 }
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 29bf2fd..b88ca8a 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -242,6 +242,121 @@
 
         self.len -= 1;
     }
+
+    /// Splices a series of nodes between two existing nodes.
+    ///
+    /// Warning: this will not check that the provided node belongs to the two existing lists.
+    #[inline]
+    unsafe fn splice_nodes(
+        &mut self,
+        existing_prev: Option<NonNull<Node<T>>>,
+        existing_next: Option<NonNull<Node<T>>>,
+        mut splice_start: NonNull<Node<T>>,
+        mut splice_end: NonNull<Node<T>>,
+        splice_length: usize,
+    ) {
+        // This method takes care not to create multiple mutable references to whole nodes at the same time,
+        // to maintain validity of aliasing pointers into `element`.
+        if let Some(mut existing_prev) = existing_prev {
+            existing_prev.as_mut().next = Some(splice_start);
+        } else {
+            self.head = Some(splice_start);
+        }
+        if let Some(mut existing_next) = existing_next {
+            existing_next.as_mut().prev = Some(splice_end);
+        } else {
+            self.tail = Some(splice_end);
+        }
+        splice_start.as_mut().prev = existing_prev;
+        splice_end.as_mut().next = existing_next;
+
+        self.len += splice_length;
+    }
+
+    /// Detaches all nodes from a linked list as a series of nodes.
+    #[inline]
+    fn detach_all_nodes(mut self) -> Option<(NonNull<Node<T>>, NonNull<Node<T>>, usize)> {
+        let head = self.head.take();
+        let tail = self.tail.take();
+        let len = mem::replace(&mut self.len, 0);
+        if let Some(head) = head {
+            let tail = tail.unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() });
+            Some((head, tail, len))
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    unsafe fn split_off_before_node(
+        &mut self,
+        split_node: Option<NonNull<Node<T>>>,
+        at: usize,
+    ) -> Self {
+        // The split node is the new head node of the second part
+        if let Some(mut split_node) = split_node {
+            let first_part_head;
+            let first_part_tail;
+            first_part_tail = split_node.as_mut().prev.take();
+            if let Some(mut tail) = first_part_tail {
+                tail.as_mut().next = None;
+                first_part_head = self.head;
+            } else {
+                first_part_head = None;
+            }
+
+            let first_part = LinkedList {
+                head: first_part_head,
+                tail: first_part_tail,
+                len: at,
+                marker: PhantomData,
+            };
+
+            // Fix the head ptr of the second part
+            self.head = Some(split_node);
+            self.len = self.len - at;
+
+            first_part
+        } else {
+            mem::replace(self, LinkedList::new())
+        }
+    }
+
+    #[inline]
+    unsafe fn split_off_after_node(
+        &mut self,
+        split_node: Option<NonNull<Node<T>>>,
+        at: usize,
+    ) -> Self {
+        // The split node is the new tail node of the first part and owns
+        // the head of the second part.
+        if let Some(mut split_node) = split_node {
+            let second_part_head;
+            let second_part_tail;
+            second_part_head = split_node.as_mut().next.take();
+            if let Some(mut head) = second_part_head {
+                head.as_mut().prev = None;
+                second_part_tail = self.tail;
+            } else {
+                second_part_tail = None;
+            }
+
+            let second_part = LinkedList {
+                head: second_part_head,
+                tail: second_part_tail,
+                len: self.len - at,
+                marker: PhantomData,
+            };
+
+            // Fix the tail ptr of the first part
+            self.tail = Some(split_node);
+            self.len = at;
+
+            second_part
+        } else {
+            mem::replace(self, LinkedList::new())
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -319,6 +434,27 @@
         }
     }
 
+    /// Moves all elements from `other` to the begin of the list.
+    #[unstable(feature = "linked_list_prepend", issue = "none")]
+    pub fn prepend(&mut self, other: &mut Self) {
+        match self.head {
+            None => mem::swap(self, other),
+            Some(mut head) => {
+                // `as_mut` is okay here because we have exclusive access to the entirety
+                // of both lists.
+                if let Some(mut other_tail) = other.tail.take() {
+                    unsafe {
+                        head.as_mut().prev = Some(other_tail);
+                        other_tail.as_mut().next = Some(head);
+                    }
+
+                    self.head = other.head.take();
+                    self.len += mem::replace(&mut other.len, 0);
+                }
+            }
+        }
+    }
+
     /// Provides a forward iterator.
     ///
     /// # Examples
@@ -373,6 +509,42 @@
         IterMut { head: self.head, tail: self.tail, len: self.len, list: self }
     }
 
+    /// Provides a cursor at the front element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
+    #[inline]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn cursor_front(&self) -> Cursor<'_, T> {
+        Cursor { index: 0, current: self.head, list: self }
+    }
+
+    /// Provides a cursor with editing operations at the front element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
+    #[inline]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> {
+        CursorMut { index: 0, current: self.head, list: self }
+    }
+
+    /// Provides a cursor at the back element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
+    #[inline]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn cursor_back(&self) -> Cursor<'_, T> {
+        Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self }
+    }
+
+    /// Provides a cursor with editing operations at the back element.
+    ///
+    /// The cursor is pointing to the "ghost" non-element if the list is empty.
+    #[inline]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> {
+        CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self }
+    }
+
     /// Returns `true` if the `LinkedList` is empty.
     ///
     /// This operation should compute in O(1) time.
@@ -703,30 +875,7 @@
             }
             iter.tail
         };
-
-        // The split node is the new tail node of the first part and owns
-        // the head of the second part.
-        let second_part_head;
-
-        unsafe {
-            second_part_head = split_node.unwrap().as_mut().next.take();
-            if let Some(mut head) = second_part_head {
-                head.as_mut().prev = None;
-            }
-        }
-
-        let second_part = LinkedList {
-            head: second_part_head,
-            tail: self.tail,
-            len: len - at,
-            marker: PhantomData,
-        };
-
-        // Fix the tail ptr of the first part
-        self.tail = split_node;
-        self.len = at;
-
-        second_part
+        unsafe { self.split_off_after_node(split_node, at) }
     }
 
     /// Creates an iterator which uses a closure to determine if an element should be removed.
@@ -986,6 +1135,388 @@
     }
 }
 
+/// A cursor over a `LinkedList`.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth.
+///
+/// Cursors always rest between two elements in the list, and index in a logically circular way.
+/// To accommodate this, there is a "ghost" non-element that yields `None` between the head and
+/// tail of the list.
+///
+/// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty.
+#[unstable(feature = "linked_list_cursors", issue = "58533")]
+pub struct Cursor<'a, T: 'a> {
+    index: usize,
+    current: Option<NonNull<Node<T>>>,
+    list: &'a LinkedList<T>,
+}
+
+#[unstable(feature = "linked_list_cursors", issue = "58533")]
+impl<T: fmt::Debug> fmt::Debug for Cursor<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("Cursor").field(&self.list).field(&self.index()).finish()
+    }
+}
+
+/// A cursor over a `LinkedList` with editing operations.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
+/// safely mutate the list during iteration. This is because the lifetime of its yielded
+/// references is tied to its own lifetime, instead of just the underlying list. This means
+/// cursors cannot yield multiple elements at once.
+///
+/// Cursors always rest between two elements in the list, and index in a logically circular way.
+/// To accommodate this, there is a "ghost" non-element that yields `None` between the head and
+/// tail of the list.
+#[unstable(feature = "linked_list_cursors", issue = "58533")]
+pub struct CursorMut<'a, T: 'a> {
+    index: usize,
+    current: Option<NonNull<Node<T>>>,
+    list: &'a mut LinkedList<T>,
+}
+
+#[unstable(feature = "linked_list_cursors", issue = "58533")]
+impl<T: fmt::Debug> fmt::Debug for CursorMut<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("CursorMut").field(&self.list).field(&self.index()).finish()
+    }
+}
+
+impl<'a, T> Cursor<'a, T> {
+    /// Returns the cursor position index within the `LinkedList`.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the
+    /// "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn index(&self) -> Option<usize> {
+        let _ = self.current?;
+        Some(self.index)
+    }
+
+    /// Moves the cursor to the next element of the `LinkedList`.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this will move it to
+    /// the first element of the `LinkedList`. If it is pointing to the last
+    /// element of the `LinkedList` then this will move it to the "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn move_next(&mut self) {
+        match self.current.take() {
+            // We had no current element; the cursor was sitting at the start position
+            // Next element should be the head of the list
+            None => {
+                self.current = self.list.head;
+                self.index = 0;
+            }
+            // We had a previous element, so let's go to its next
+            Some(current) => unsafe {
+                self.current = current.as_ref().next;
+                self.index += 1;
+            },
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `LinkedList`.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this will move it to
+    /// the last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this will move it to the "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn move_prev(&mut self) {
+        match self.current.take() {
+            // No current. We're at the start of the list. Yield None and jump to the end.
+            None => {
+                self.current = self.list.tail;
+                self.index = self.list.len().checked_sub(1).unwrap_or(0);
+            }
+            // Have a prev. Yield it and go to the previous element.
+            Some(current) => unsafe {
+                self.current = current.as_ref().prev;
+                self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len());
+            },
+        }
+    }
+
+    /// Returns a reference to the element that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the
+    /// "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn current(&self) -> Option<&'a T> {
+        unsafe { self.current.map(|current| &(*current.as_ptr()).element) }
+    }
+
+    /// Returns a reference to the next element.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this returns
+    /// the first element of the `LinkedList`. If it is pointing to the last
+    /// element of the `LinkedList` then this returns `None`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn peek_next(&self) -> Option<&'a T> {
+        unsafe {
+            let next = match self.current {
+                None => self.list.head,
+                Some(current) => current.as_ref().next,
+            };
+            next.map(|next| &(*next.as_ptr()).element)
+        }
+    }
+
+    /// Returns a reference to the previous element.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this returns
+    /// the last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this returns `None`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn peek_prev(&self) -> Option<&'a T> {
+        unsafe {
+            let prev = match self.current {
+                None => self.list.tail,
+                Some(current) => current.as_ref().prev,
+            };
+            prev.map(|prev| &(*prev.as_ptr()).element)
+        }
+    }
+}
+
+impl<'a, T> CursorMut<'a, T> {
+    /// Returns the cursor position index within the `LinkedList`.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the
+    /// "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn index(&self) -> Option<usize> {
+        let _ = self.current?;
+        Some(self.index)
+    }
+
+    /// Moves the cursor to the next element of the `LinkedList`.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this will move it to
+    /// the first element of the `LinkedList`. If it is pointing to the last
+    /// element of the `LinkedList` then this will move it to the "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn move_next(&mut self) {
+        match self.current.take() {
+            // We had no current element; the cursor was sitting at the start position
+            // Next element should be the head of the list
+            None => {
+                self.current = self.list.head;
+                self.index = 0;
+            }
+            // We had a previous element, so let's go to its next
+            Some(current) => unsafe {
+                self.current = current.as_ref().next;
+                self.index += 1;
+            },
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `LinkedList`.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this will move it to
+    /// the last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this will move it to the "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn move_prev(&mut self) {
+        match self.current.take() {
+            // No current. We're at the start of the list. Yield None and jump to the end.
+            None => {
+                self.current = self.list.tail;
+                self.index = self.list.len().checked_sub(1).unwrap_or(0);
+            }
+            // Have a prev. Yield it and go to the previous element.
+            Some(current) => unsafe {
+                self.current = current.as_ref().prev;
+                self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len());
+            },
+        }
+    }
+
+    /// Returns a reference to the element that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the
+    /// "ghost" non-element.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn current(&mut self) -> Option<&mut T> {
+        unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) }
+    }
+
+    /// Returns a reference to the next element.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this returns
+    /// the first element of the `LinkedList`. If it is pointing to the last
+    /// element of the `LinkedList` then this returns `None`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn peek_next(&mut self) -> Option<&mut T> {
+        unsafe {
+            let next = match self.current {
+                None => self.list.head,
+                Some(current) => current.as_ref().next,
+            };
+            next.map(|next| &mut (*next.as_ptr()).element)
+        }
+    }
+
+    /// Returns a reference to the previous element.
+    ///
+    /// If the cursor is pointing to the "ghost" non-element then this returns
+    /// the last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this returns `None`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn peek_prev(&mut self) -> Option<&mut T> {
+        unsafe {
+            let prev = match self.current {
+                None => self.list.tail,
+                Some(current) => current.as_ref().prev,
+            };
+            prev.map(|prev| &mut (*prev.as_ptr()).element)
+        }
+    }
+
+    /// Returns a read-only cursor pointing to the current element.
+    ///
+    /// The lifetime of the returned `Cursor` is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T> {
+        Cursor { list: self.list, current: self.current, index: self.index }
+    }
+}
+
+// Now the list editing operations
+
+impl<'a, T> CursorMut<'a, T> {
+    /// Inserts a new element into the `LinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the "ghost" non-element then the new element is
+    /// inserted at the front of the `LinkedList`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn insert_after(&mut self, item: T) {
+        unsafe {
+            let spliced_node = Box::into_raw_non_null(Box::new(Node::new(item)));
+            let node_next = match self.current {
+                None => self.list.head,
+                Some(node) => node.as_ref().next,
+            };
+            self.list.splice_nodes(self.current, node_next, spliced_node, spliced_node, 1);
+            if self.current.is_none() {
+                // The "ghost" non-element's index has changed.
+                self.index = self.list.len;
+            }
+        }
+    }
+
+    /// Inserts a new element into the `LinkedList` before the current one.
+    ///
+    /// If the cursor is pointing at the "ghost" non-element then the new element is
+    /// inserted at the end of the `LinkedList`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn insert_before(&mut self, item: T) {
+        unsafe {
+            let spliced_node = Box::into_raw_non_null(Box::new(Node::new(item)));
+            let node_prev = match self.current {
+                None => self.list.tail,
+                Some(node) => node.as_ref().prev,
+            };
+            self.list.splice_nodes(node_prev, self.current, spliced_node, spliced_node, 1);
+            self.index += 1;
+        }
+    }
+
+    /// Removes the current element from the `LinkedList`.
+    ///
+    /// The element that was removed is returned, and the cursor is
+    /// moved to point to the next element in the `LinkedList`.
+    ///
+    /// If the cursor is currently pointing to the "ghost" non-element then no element
+    /// is removed and `None` is returned.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn remove_current(&mut self) -> Option<T> {
+        let unlinked_node = self.current?;
+        unsafe {
+            self.current = unlinked_node.as_ref().next;
+            self.list.unlink_node(unlinked_node);
+            let unlinked_node = Box::from_raw(unlinked_node.as_ptr());
+            Some(unlinked_node.element)
+        }
+    }
+
+    /// Inserts the elements from the given `LinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the "ghost" non-element then the new elements are
+    /// inserted at the start of the `LinkedList`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn splice_after(&mut self, list: LinkedList<T>) {
+        unsafe {
+            let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() {
+                Some(parts) => parts,
+                _ => return,
+            };
+            let node_next = match self.current {
+                None => self.list.head,
+                Some(node) => node.as_ref().next,
+            };
+            self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len);
+            if self.current.is_none() {
+                // The "ghost" non-element's index has changed.
+                self.index = self.list.len;
+            }
+        }
+    }
+
+    /// Inserts the elements from the given `LinkedList` before the current one.
+    ///
+    /// If the cursor is pointing at the "ghost" non-element then the new elements are
+    /// inserted at the end of the `LinkedList`.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn splice_before(&mut self, list: LinkedList<T>) {
+        unsafe {
+            let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() {
+                Some(parts) => parts,
+                _ => return,
+            };
+            let node_prev = match self.current {
+                None => self.list.tail,
+                Some(node) => node.as_ref().prev,
+            };
+            self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len);
+            self.index += splice_len;
+        }
+    }
+
+    /// Splits the list into two after the current element. This will return a
+    /// new list consisting of everything after the cursor, with the original
+    /// list retaining everything before.
+    ///
+    /// If the cursor is pointing at the "ghost" non-element then the entire contents
+    /// of the `LinkedList` are moved.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn split_after(&mut self) -> LinkedList<T> {
+        let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 };
+        if self.index == self.list.len {
+            // The "ghost" non-element's index has changed to 0.
+            self.index = 0;
+        }
+        unsafe { self.list.split_off_after_node(self.current, split_off_idx) }
+    }
+
+    /// Splits the list into two before the current element. This will return a
+    /// new list consisting of everything before the cursor, with the original
+    /// list retaining everything after.
+    ///
+    /// If the cursor is pointing at the "ghost" non-element then the entire contents
+    /// of the `LinkedList` are moved.
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn split_before(&mut self) -> LinkedList<T> {
+        let split_off_idx = self.index;
+        self.index = 0;
+        unsafe { self.list.split_off_before_node(self.current, split_off_idx) }
+    }
+}
+
 /// An iterator produced by calling `drain_filter` on LinkedList.
 #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
 pub struct DrainFilter<'a, T: 'a, F: 'a>
diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs
index 1b1d8ea..085f734 100644
--- a/src/liballoc/collections/linked_list/tests.rs
+++ b/src/liballoc/collections/linked_list/tests.rs
@@ -304,3 +304,155 @@
     assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]);
     assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]);
 }
+
+#[test]
+fn test_cursor_move_peek() {
+    let mut m: LinkedList<u32> = LinkedList::new();
+    m.extend(&[1, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_front();
+    assert_eq!(cursor.current(), Some(&1));
+    assert_eq!(cursor.peek_next(), Some(&2));
+    assert_eq!(cursor.peek_prev(), None);
+    assert_eq!(cursor.index(), Some(0));
+    cursor.move_prev();
+    assert_eq!(cursor.current(), None);
+    assert_eq!(cursor.peek_next(), Some(&1));
+    assert_eq!(cursor.peek_prev(), Some(&6));
+    assert_eq!(cursor.index(), None);
+    cursor.move_next();
+    cursor.move_next();
+    assert_eq!(cursor.current(), Some(&2));
+    assert_eq!(cursor.peek_next(), Some(&3));
+    assert_eq!(cursor.peek_prev(), Some(&1));
+    assert_eq!(cursor.index(), Some(1));
+
+    let mut cursor = m.cursor_back();
+    assert_eq!(cursor.current(), Some(&6));
+    assert_eq!(cursor.peek_next(), None);
+    assert_eq!(cursor.peek_prev(), Some(&5));
+    assert_eq!(cursor.index(), Some(5));
+    cursor.move_next();
+    assert_eq!(cursor.current(), None);
+    assert_eq!(cursor.peek_next(), Some(&1));
+    assert_eq!(cursor.peek_prev(), Some(&6));
+    assert_eq!(cursor.index(), None);
+    cursor.move_prev();
+    cursor.move_prev();
+    assert_eq!(cursor.current(), Some(&5));
+    assert_eq!(cursor.peek_next(), Some(&6));
+    assert_eq!(cursor.peek_prev(), Some(&4));
+    assert_eq!(cursor.index(), Some(4));
+
+    let mut m: LinkedList<u32> = LinkedList::new();
+    m.extend(&[1, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_front_mut();
+    assert_eq!(cursor.current(), Some(&mut 1));
+    assert_eq!(cursor.peek_next(), Some(&mut 2));
+    assert_eq!(cursor.peek_prev(), None);
+    assert_eq!(cursor.index(), Some(0));
+    cursor.move_prev();
+    assert_eq!(cursor.current(), None);
+    assert_eq!(cursor.peek_next(), Some(&mut 1));
+    assert_eq!(cursor.peek_prev(), Some(&mut 6));
+    assert_eq!(cursor.index(), None);
+    cursor.move_next();
+    cursor.move_next();
+    assert_eq!(cursor.current(), Some(&mut 2));
+    assert_eq!(cursor.peek_next(), Some(&mut 3));
+    assert_eq!(cursor.peek_prev(), Some(&mut 1));
+    assert_eq!(cursor.index(), Some(1));
+    let mut cursor2 = cursor.as_cursor();
+    assert_eq!(cursor2.current(), Some(&2));
+    assert_eq!(cursor2.index(), Some(1));
+    cursor2.move_next();
+    assert_eq!(cursor2.current(), Some(&3));
+    assert_eq!(cursor2.index(), Some(2));
+    assert_eq!(cursor.current(), Some(&mut 2));
+    assert_eq!(cursor.index(), Some(1));
+
+    let mut m: LinkedList<u32> = LinkedList::new();
+    m.extend(&[1, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_back_mut();
+    assert_eq!(cursor.current(), Some(&mut 6));
+    assert_eq!(cursor.peek_next(), None);
+    assert_eq!(cursor.peek_prev(), Some(&mut 5));
+    assert_eq!(cursor.index(), Some(5));
+    cursor.move_next();
+    assert_eq!(cursor.current(), None);
+    assert_eq!(cursor.peek_next(), Some(&mut 1));
+    assert_eq!(cursor.peek_prev(), Some(&mut 6));
+    assert_eq!(cursor.index(), None);
+    cursor.move_prev();
+    cursor.move_prev();
+    assert_eq!(cursor.current(), Some(&mut 5));
+    assert_eq!(cursor.peek_next(), Some(&mut 6));
+    assert_eq!(cursor.peek_prev(), Some(&mut 4));
+    assert_eq!(cursor.index(), Some(4));
+    let mut cursor2 = cursor.as_cursor();
+    assert_eq!(cursor2.current(), Some(&5));
+    assert_eq!(cursor2.index(), Some(4));
+    cursor2.move_prev();
+    assert_eq!(cursor2.current(), Some(&4));
+    assert_eq!(cursor2.index(), Some(3));
+    assert_eq!(cursor.current(), Some(&mut 5));
+    assert_eq!(cursor.index(), Some(4));
+}
+
+#[test]
+fn test_cursor_mut_insert() {
+    let mut m: LinkedList<u32> = LinkedList::new();
+    m.extend(&[1, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_front_mut();
+    cursor.insert_before(7);
+    cursor.insert_after(8);
+    check_links(&m);
+    assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[7, 1, 8, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_front_mut();
+    cursor.move_prev();
+    cursor.insert_before(9);
+    cursor.insert_after(10);
+    check_links(&m);
+    assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[10, 7, 1, 8, 2, 3, 4, 5, 6, 9]);
+    let mut cursor = m.cursor_front_mut();
+    cursor.move_prev();
+    assert_eq!(cursor.remove_current(), None);
+    cursor.move_next();
+    cursor.move_next();
+    assert_eq!(cursor.remove_current(), Some(7));
+    cursor.move_prev();
+    cursor.move_prev();
+    cursor.move_prev();
+    assert_eq!(cursor.remove_current(), Some(9));
+    cursor.move_next();
+    assert_eq!(cursor.remove_current(), Some(10));
+    check_links(&m);
+    assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[1, 8, 2, 3, 4, 5, 6]);
+    let mut cursor = m.cursor_front_mut();
+    let mut p: LinkedList<u32> = LinkedList::new();
+    p.extend(&[100, 101, 102, 103]);
+    let mut q: LinkedList<u32> = LinkedList::new();
+    q.extend(&[200, 201, 202, 203]);
+    cursor.splice_after(p);
+    cursor.splice_before(q);
+    check_links(&m);
+    assert_eq!(
+        m.iter().cloned().collect::<Vec<_>>(),
+        &[200, 201, 202, 203, 1, 100, 101, 102, 103, 8, 2, 3, 4, 5, 6]
+    );
+    let mut cursor = m.cursor_front_mut();
+    cursor.move_prev();
+    let tmp = cursor.split_before();
+    assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]);
+    m = tmp;
+    let mut cursor = m.cursor_front_mut();
+    cursor.move_next();
+    cursor.move_next();
+    cursor.move_next();
+    cursor.move_next();
+    cursor.move_next();
+    cursor.move_next();
+    let tmp = cursor.split_after();
+    assert_eq!(tmp.into_iter().collect::<Vec<_>>(), &[102, 103, 8, 2, 3, 4, 5, 6]);
+    check_links(&m);
+    assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[200, 201, 202, 203, 1, 100, 101]);
+}
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 3080a8b..b176e0f 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -565,9 +565,19 @@
     /// ```
     #[stable(feature = "rc_raw", since = "1.17.0")]
     pub fn into_raw(this: Self) -> *const T {
-        let ptr: *const T = &*this;
+        let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
+        let fake_ptr = ptr as *mut T;
         mem::forget(this);
-        ptr
+
+        // SAFETY: This cannot go through Deref::deref.
+        // Instead, we manually offset the pointer rather than manifesting a reference.
+        // This is so that the returned pointer retains the same provenance as our pointer.
+        // This is required so that e.g. `get_mut` can write through the pointer
+        // after the Rc is recovered through `from_raw`.
+        unsafe {
+            let offset = data_offset(&(*ptr).value);
+            set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset))
+        }
     }
 
     /// Constructs an `Rc` from a raw pointer.
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index dc53ad2..4aa0190 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -545,9 +545,19 @@
     /// ```
     #[stable(feature = "rc_raw", since = "1.17.0")]
     pub fn into_raw(this: Self) -> *const T {
-        let ptr: *const T = &*this;
+        let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
+        let fake_ptr = ptr as *mut T;
         mem::forget(this);
-        ptr
+
+        // SAFETY: This cannot go through Deref::deref.
+        // Instead, we manually offset the pointer rather than manifesting a reference.
+        // This is so that the returned pointer retains the same provenance as our pointer.
+        // This is required so that e.g. `get_mut` can write through the pointer
+        // after the Arc is recovered through `from_raw`.
+        unsafe {
+            let offset = data_offset(&(*ptr).data);
+            set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset))
+        }
     }
 
     /// Constructs an `Arc` from a raw pointer.
diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs
index 35ce135..f5be72c 100644
--- a/src/liballoc/tests/btree/map.rs
+++ b/src/liballoc/tests/btree/map.rs
@@ -4,6 +4,7 @@
 use std::fmt::Debug;
 use std::iter::FromIterator;
 use std::ops::Bound::{self, Excluded, Included, Unbounded};
+use std::ops::RangeBounds;
 use std::rc::Rc;
 
 use super::DeterministicRng;
@@ -68,6 +69,11 @@
     assert_eq!(map.last_key_value(), None);
     assert_eq!(map.keys().count(), 0);
     assert_eq!(map.values().count(), 0);
+    assert_eq!(map.range(..).next(), None);
+    assert_eq!(map.range(..1).next(), None);
+    assert_eq!(map.range(1..).next(), None);
+    assert_eq!(map.range(1..=1).next(), None);
+    assert_eq!(map.range(1..2).next(), None);
     assert_eq!(map.insert(1, 1), None);
 
     // 1 key-value pair:
@@ -118,6 +124,11 @@
     assert_eq!(map.last_key_value(), None);
     assert_eq!(map.keys().count(), 0);
     assert_eq!(map.values().count(), 0);
+    assert_eq!(map.range(..).next(), None);
+    assert_eq!(map.range(..1).next(), None);
+    assert_eq!(map.range(1..).next(), None);
+    assert_eq!(map.range(1..=1).next(), None);
+    assert_eq!(map.range(1..2).next(), None);
     assert_eq!(map.remove(&1), None);
 }
 
@@ -128,7 +139,6 @@
     #[cfg(miri)]
     let size = 200;
 
-    // Forwards
     let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
 
     fn test<T>(size: usize, mut iter: T)
@@ -154,7 +164,6 @@
     #[cfg(miri)]
     let size = 200;
 
-    // Forwards
     let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
 
     fn test<T>(size: usize, mut iter: T)
@@ -275,7 +284,6 @@
     #[cfg(miri)]
     let size = 200;
 
-    // Forwards
     let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
 
     fn test<T>(size: usize, mut iter: T)
@@ -299,27 +307,147 @@
     test(size, map.into_iter());
 }
 
-#[test]
-fn test_range_small() {
-    let size = 5;
-
-    // Forwards
-    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    let mut j = 0;
-    for ((&k, &v), i) in map.range(2..).zip(2..size) {
-        assert_eq!(k, i);
-        assert_eq!(v, i);
-        j += 1;
-    }
-    assert_eq!(j, size - 2);
+fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> {
+    map.range(range)
+        .map(|(&k, &v)| {
+            assert_eq!(k, v);
+            k
+        })
+        .collect()
 }
 
 #[test]
-fn test_range_inclusive() {
-    let size = 500;
+fn test_range_small() {
+    let size = 4;
 
-    let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect();
+    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+    let all: Vec<_> = (1..=size).collect();
+    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+    assert_eq!(range_keys(&map, ..), all);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
+
+    assert_eq!(range_keys(&map, ..3), vec![1, 2]);
+    assert_eq!(range_keys(&map, 3..), vec![3, 4]);
+    assert_eq!(range_keys(&map, 2..=3), vec![2, 3]);
+}
+
+#[test]
+fn test_range_depth_2() {
+    // Assuming that node.CAPACITY is 11, having 12 pairs implies a depth 2 tree
+    // with 2 leaves. Depending on details we don't want or need to rely upon,
+    // the single key at the root will be 6 or 7.
+
+    let map: BTreeMap<_, _> = (1..=12).map(|i| (i, i)).collect();
+    for &root in &[6, 7] {
+        assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]);
+        assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]);
+        assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]);
+        assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]);
+
+        assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]);
+        assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]);
+        assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]);
+        assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]);
+    }
+}
+
+#[test]
+fn test_range_large() {
+    let size = 200;
+
+    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+    let all: Vec<_> = (1..=size).collect();
+    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+    assert_eq!(range_keys(&map, ..), all);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
 
     fn check<'a, L, R>(lhs: L, rhs: R)
     where
@@ -331,18 +459,9 @@
         assert_eq!(lhs, rhs);
     }
 
-    check(map.range(size + 1..=size + 1), vec![]);
-    check(map.range(size..=size), vec![(&size, &size)]);
-    check(map.range(size..=size + 1), vec![(&size, &size)]);
-    check(map.range(0..=0), vec![(&0, &0)]);
-    check(map.range(0..=size - 1), map.range(..size));
-    check(map.range(-1..=-1), vec![]);
-    check(map.range(-1..=size), map.range(..));
-    check(map.range(..=size), map.range(..));
-    check(map.range(..=200), map.range(..201));
+    check(map.range(..=100), map.range(..101));
     check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
-    check(map.range(-1..=0), vec![(&0, &0)]);
-    check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]);
+    check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]);
 }
 
 #[test]
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 3fdee8b..c1ae67a 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -11,6 +11,7 @@
 #![feature(associated_type_bounds)]
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(binary_heap_drain_sorted)]
+#![feature(vec_remove_item)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index f5f8d88..e9cbf62 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1696,13 +1696,14 @@
     /// # Examples
     ///
     /// ```
+    /// # #![feature(vec_remove_item)]
     /// let mut vec = vec![1, 2, 3, 1];
     ///
     /// vec.remove_item(&1);
     ///
     /// assert_eq!(vec, vec![2, 3, 1]);
     /// ```
-    #[stable(feature = "vec_remove_item", since = "1.42.0")]
+    #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")]
     pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
     where
         T: PartialEq<V>,
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index beb0bac..2a3d92e 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -21,7 +21,6 @@
 extern crate alloc;
 
 use rustc_data_structures::cold_path;
-use rustc_data_structures::sync::MTLock;
 use smallvec::SmallVec;
 
 use std::cell::{Cell, RefCell};
@@ -116,11 +115,6 @@
 }
 
 impl<T> TypedArena<T> {
-    pub fn in_arena(&self, ptr: *const T) -> bool {
-        let ptr = ptr as *const T as *mut T;
-
-        self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
-    }
     /// Allocates an object in the `TypedArena`, returning a reference to it.
     #[inline]
     pub fn alloc(&self, object: T) -> &mut T {
@@ -334,12 +328,6 @@
 }
 
 impl DroplessArena {
-    pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
-        let ptr = ptr as *const u8 as *mut u8;
-
-        self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
-    }
-
     #[inline]
     fn align(&self, align: usize) {
         let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
@@ -500,66 +488,5 @@
     }
 }
 
-#[derive(Default)]
-// FIXME(@Zoxc): this type is entirely unused in rustc
-pub struct SyncTypedArena<T> {
-    lock: MTLock<TypedArena<T>>,
-}
-
-impl<T> SyncTypedArena<T> {
-    #[inline(always)]
-    pub fn alloc(&self, object: T) -> &mut T {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
-    }
-
-    #[inline(always)]
-    pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
-    where
-        T: Copy,
-    {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
-    }
-
-    #[inline(always)]
-    pub fn clear(&mut self) {
-        self.lock.get_mut().clear();
-    }
-}
-
-#[derive(Default)]
-pub struct SyncDroplessArena {
-    lock: MTLock<DroplessArena>,
-}
-
-impl SyncDroplessArena {
-    #[inline(always)]
-    pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
-        self.lock.lock().in_arena(ptr)
-    }
-
-    #[inline(always)]
-    pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc_raw(bytes, align) as *mut [u8]) }
-    }
-
-    #[inline(always)]
-    pub fn alloc<T>(&self, object: T) -> &mut T {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
-    }
-
-    #[inline(always)]
-    pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
-    where
-        T: Copy,
-    {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
-    }
-}
-
 #[cfg(test)]
 mod tests;
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index b2d4b1b..09f743f 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -17,7 +17,7 @@
 #[derive(Debug)]
 pub struct Excess(pub NonNull<u8>, pub usize);
 
-fn size_align<T>() -> (usize, usize) {
+const fn size_align<T>() -> (usize, usize) {
     (mem::size_of::<T>(), mem::align_of::<T>())
 }
 
@@ -64,8 +64,9 @@
     ///    must not overflow (i.e., the rounded value must be less than
     ///    `usize::MAX`).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
+    pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
         if !align.is_power_of_two() {
             return Err(LayoutErr { private: () });
         }
@@ -106,28 +107,30 @@
 
     /// The minimum size in bytes for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn size(&self) -> usize {
+    pub const fn size(&self) -> usize {
         self.size_
     }
 
     /// The minimum byte alignment for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn align(&self) -> usize {
+    pub const fn align(&self) -> usize {
         self.align_.get()
     }
 
     /// Constructs a `Layout` suitable for holding a value of type `T`.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
     #[inline]
-    pub fn new<T>() -> Self {
+    pub const fn new<T>() -> Self {
         let (size, align) = size_align::<T>();
         // Note that the align is guaranteed by rustc to be a power of two and
         // the size+align combo is guaranteed to fit in our address space. As a
         // result use the unchecked constructor here to avoid inserting code
         // that panics if it isn't optimized well enough.
-        debug_assert!(Layout::from_size_align(size, align).is_ok());
         unsafe { Layout::from_size_align_unchecked(size, align) }
     }
 
@@ -181,8 +184,9 @@
     /// address for the whole allocated block of memory. One way to
     /// satisfy this constraint is to ensure `align <= self.align()`.
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
     #[inline]
-    pub fn padding_needed_for(&self, align: usize) -> usize {
+    pub const fn padding_needed_for(&self, align: usize) -> usize {
         let len = self.size();
 
         // Rounded up value is:
@@ -521,7 +525,8 @@
     /// The memory may or may not have been deallocated,
     /// and should be considered unusable (unless of course it was
     /// transferred back to the caller again via the return value of
-    /// this method).
+    /// this method). The new memory block is allocated with `layout`, but
+    /// with the `size` updated to `new_size`.
     ///
     /// If this method returns null, then ownership of the memory
     /// block has not been transferred to this allocator, and the
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 4afea12..af02e84 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -476,11 +476,15 @@
 ///
 /// This is intended for diagnostic use. The exact contents and format of the
 /// string are not specified, other than being a best-effort description of the
-/// type. For example, `type_name_of::<Option<String>>(None)` could return
+/// type. For example, `type_name_of_val::<Option<String>>(None)` could return
 /// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
 /// `"foobar"`. In addition, the output may change between versions of the
 /// compiler.
 ///
+/// This function does not resolve trait objects,
+/// meaning that `type_name_of_val(&7u32 as &dyn Debug)`
+/// may return `"dyn Debug"`, but not `"u32"`.
+///
 /// The type name should not be considered a unique identifier of a type;
 /// multiple types may share the same type name.
 ///
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 4fcd0d9..e7eecf7 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -187,8 +187,6 @@
 //! ```
 //!
 
-// ignore-tidy-undocumented-unsafe
-
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cmp::Ordering;
@@ -368,6 +366,10 @@
         if ptr::eq(self, other) {
             return;
         }
+        // SAFETY: This can be risky if called from separate threads, but `Cell`
+        // is `!Sync` so this won't happen. This also won't invalidate any
+        // pointers since `Cell` makes sure nothing else will be pointing into
+        // either of these `Cell`s.
         unsafe {
             ptr::swap(self.value.get(), other.value.get());
         }
@@ -387,6 +389,8 @@
     /// ```
     #[stable(feature = "move_cell", since = "1.17.0")]
     pub fn replace(&self, val: T) -> T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen.
         mem::replace(unsafe { &mut *self.value.get() }, val)
     }
 
@@ -423,6 +427,8 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen.
         unsafe { *self.value.get() }
     }
 
@@ -491,6 +497,9 @@
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
     pub fn get_mut(&mut self) -> &mut T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen, and `&mut` guarantees
+        // unique access.
         unsafe { &mut *self.value.get() }
     }
 
@@ -510,6 +519,7 @@
     #[inline]
     #[stable(feature = "as_cell", since = "1.37.0")]
     pub fn from_mut(t: &mut T) -> &Cell<T> {
+        // SAFETY: `&mut` ensures unique access.
         unsafe { &*(t as *mut T as *const Cell<T>) }
     }
 }
@@ -553,6 +563,7 @@
     /// ```
     #[stable(feature = "as_cell", since = "1.37.0")]
     pub fn as_slice_of_cells(&self) -> &[Cell<T>] {
+        // SAFETY: `Cell<T>` has the same memory layout as `T`.
         unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
     }
 }
@@ -816,6 +827,8 @@
     #[inline]
     pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
         match BorrowRef::new(&self.borrow) {
+            // SAFETY: `BorrowRef` ensures that there is only immutable access
+            // to the value while borrowed.
             Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }),
             None => Err(BorrowError { _private: () }),
         }
@@ -891,6 +904,7 @@
     #[inline]
     pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
         match BorrowRefMut::new(&self.borrow) {
+            // SAFETY: `BorrowRef` guarantees unique access.
             Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }),
             None => Err(BorrowMutError { _private: () }),
         }
@@ -940,6 +954,7 @@
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
     pub fn get_mut(&mut self) -> &mut T {
+        // SAFETY: `&mut` guarantees unique access.
         unsafe { &mut *self.value.get() }
     }
 
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index fe5d168..c341bb5 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -3,7 +3,7 @@
 use crate::slice;
 use crate::str::from_utf8_unchecked_mut;
 use crate::unicode::printable::is_printable;
-use crate::unicode::tables::{conversions, derived_property, general_category, property};
+use crate::unicode::{self, conversions};
 
 use super::*;
 
@@ -552,7 +552,7 @@
     pub fn is_alphabetic(self) -> bool {
         match self {
             'a'..='z' | 'A'..='Z' => true,
-            c => c > '\x7f' && derived_property::Alphabetic(c),
+            c => c > '\x7f' && unicode::Alphabetic(c),
         }
     }
 
@@ -583,7 +583,7 @@
     pub fn is_lowercase(self) -> bool {
         match self {
             'a'..='z' => true,
-            c => c > '\x7f' && derived_property::Lowercase(c),
+            c => c > '\x7f' && unicode::Lowercase(c),
         }
     }
 
@@ -614,7 +614,7 @@
     pub fn is_uppercase(self) -> bool {
         match self {
             'A'..='Z' => true,
-            c => c > '\x7f' && derived_property::Uppercase(c),
+            c => c > '\x7f' && unicode::Uppercase(c),
         }
     }
 
@@ -642,7 +642,7 @@
     pub fn is_whitespace(self) -> bool {
         match self {
             ' ' | '\x09'..='\x0d' => true,
-            c => c > '\x7f' && property::White_Space(c),
+            c => c > '\x7f' && unicode::White_Space(c),
         }
     }
 
@@ -693,7 +693,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_control(self) -> bool {
-        general_category::Cc(self)
+        unicode::Cc(self)
     }
 
     /// Returns `true` if this `char` has the `Grapheme_Extend` property.
@@ -707,7 +707,7 @@
     /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
     #[inline]
     pub(crate) fn is_grapheme_extended(self) -> bool {
-        derived_property::Grapheme_Extend(self)
+        unicode::Grapheme_Extend(self)
     }
 
     /// Returns `true` if this `char` has one of the general categories for numbers.
@@ -739,7 +739,7 @@
     pub fn is_numeric(self) -> bool {
         match self {
             '0'..='9' => true,
-            c => c > '\x7f' && general_category::N(c),
+            c => c > '\x7f' && unicode::N(c),
         }
     }
 
diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs
index a655ee6..cf5576e 100644
--- a/src/libcore/char/mod.rs
+++ b/src/libcore/char/mod.rs
@@ -37,9 +37,9 @@
 
 // unstable re-exports
 #[unstable(feature = "unicode_version", issue = "49726")]
-pub use crate::unicode::tables::UNICODE_VERSION;
-#[unstable(feature = "unicode_version", issue = "49726")]
 pub use crate::unicode::version::UnicodeVersion;
+#[unstable(feature = "unicode_version", issue = "49726")]
+pub use crate::unicode::UNICODE_VERSION;
 
 use crate::fmt::{self, Write};
 use crate::iter::FusedIterator;
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 06e7e45..3ea4baa 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -821,10 +821,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lt(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Less) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Less))
     }
 
     /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
@@ -843,10 +840,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn le(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Less) | Some(Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Less) | Some(Equal))
     }
 
     /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
@@ -864,10 +858,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn gt(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Greater) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Greater))
     }
 
     /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
@@ -886,10 +877,7 @@
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn ge(&self, other: &Rhs) -> bool {
-        match self.partial_cmp(other) {
-            Some(Greater) | Some(Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Greater) | Some(Equal))
     }
 }
 
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index 626eb1e..8ba0e42 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -133,7 +133,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut DebugStruct<'a, 'b> {
+    pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
                 if !self.has_fields {
@@ -159,6 +159,62 @@
         self
     }
 
+    /// Marks the struct as non-exhaustive, indicating to the reader that there are some other
+    /// fields that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(debug_non_exhaustive)]
+    /// use std::fmt;
+    ///
+    /// struct Bar {
+    ///     bar: i32,
+    ///     hidden: f32,
+    /// }
+    ///
+    /// impl fmt::Debug for Bar {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         fmt.debug_struct("Bar")
+    ///            .field("bar", &self.bar)
+    ///            .finish_non_exhaustive() // Show that some other field(s) exist.
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Bar { bar: 10, hidden: 1.0 }),
+    ///     "Bar { bar: 10, .. }",
+    /// );
+    /// ```
+    #[unstable(feature = "debug_non_exhaustive", issue = "67364")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.result = self.result.and_then(|_| {
+            // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
+            if self.is_pretty() {
+                if !self.has_fields {
+                    self.fmt.write_str(" {\n")?;
+                }
+                let mut slot = None;
+                let mut state = Default::default();
+                let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
+                writer.write_str("..\n")?;
+            } else {
+                if self.has_fields {
+                    self.fmt.write_str(", ..")?;
+                } else {
+                    self.fmt.write_str(" { ..")?;
+                }
+            }
+            if self.is_pretty() {
+                self.fmt.write_str("}")?
+            } else {
+                self.fmt.write_str(" }")?;
+            }
+            Ok(())
+        });
+        self.result
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Examples
@@ -274,7 +330,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut DebugTuple<'a, 'b> {
+    pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
                 if self.fields == 0 {
@@ -436,7 +492,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugSet<'a, 'b> {
+    pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
         self.inner.entry(entry);
         self
     }
@@ -465,7 +521,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugSet<'a, 'b>
+    pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
     where
         D: fmt::Debug,
         I: IntoIterator<Item = D>,
@@ -568,7 +624,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugList<'a, 'b> {
+    pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
         self.inner.entry(entry);
         self
     }
@@ -597,7 +653,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugList<'a, 'b>
+    pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
     where
         D: fmt::Debug,
         I: IntoIterator<Item = D>,
@@ -704,7 +760,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
+    pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut Self {
         self.key(key).value(value)
     }
 
@@ -741,7 +797,7 @@
     /// );
     /// ```
     #[unstable(feature = "debug_map_key_value", reason = "recently added", issue = "62482")]
-    pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
+    pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self {
         self.result = self.result.and_then(|_| {
             assert!(
                 !self.has_key,
@@ -806,7 +862,7 @@
     /// );
     /// ```
     #[unstable(feature = "debug_map_key_value", reason = "recently added", issue = "62482")]
-    pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
+    pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self {
         self.result = self.result.and_then(|_| {
             assert!(self.has_key, "attempted to format a map value before its key");
 
@@ -852,7 +908,7 @@
     /// );
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
-    pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
+    pub fn entries<K, V, I>(&mut self, entries: I) -> &mut Self
     where
         K: fmt::Debug,
         V: fmt::Debug,
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 6c8d162..900ef63 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -10,7 +10,6 @@
 use crate::num::flt2dec;
 use crate::ops::Deref;
 use crate::result;
-use crate::slice;
 use crate::str;
 
 mod builders;
@@ -234,8 +233,6 @@
     precision: Option<usize>,
 
     buf: &'a mut (dyn Write + 'a),
-    curarg: slice::Iter<'a, ArgumentV1<'a>>,
-    args: &'a [ArgumentV1<'a>],
 }
 
 // NB. Argument is essentially an optimized partially applied formatting function,
@@ -1043,8 +1040,6 @@
         buf: output,
         align: rt::v1::Alignment::Unknown,
         fill: ' ',
-        args: args.args,
-        curarg: args.args.iter(),
     };
 
     let mut idx = 0;
@@ -1063,7 +1058,7 @@
             // a string piece.
             for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
                 formatter.buf.write_str(*piece)?;
-                formatter.run(arg)?;
+                run(&mut formatter, arg, &args.args)?;
                 idx += 1;
             }
         }
@@ -1077,6 +1072,39 @@
     Ok(())
 }
 
+fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {
+    fmt.fill = arg.format.fill;
+    fmt.align = arg.format.align;
+    fmt.flags = arg.format.flags;
+    fmt.width = getcount(args, &arg.format.width);
+    fmt.precision = getcount(args, &arg.format.precision);
+
+    // Extract the correct argument
+    let value = {
+        #[cfg(bootstrap)]
+        {
+            match arg.position {
+                rt::v1::Position::At(i) => args[i],
+            }
+        }
+        #[cfg(not(bootstrap))]
+        {
+            args[arg.position]
+        }
+    };
+
+    // Then actually do some printing
+    (value.formatter)(value.value, fmt)
+}
+
+fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {
+    match *cnt {
+        rt::v1::Count::Is(n) => Some(n),
+        rt::v1::Count::Implied => None,
+        rt::v1::Count::Param(i) => args[i].as_usize(),
+    }
+}
+
 /// Padding after the end of something. Returned by `Formatter::padding`.
 #[must_use = "don't forget to write the post padding"]
 struct PostPadding {
@@ -1114,41 +1142,6 @@
             align: self.align,
             width: self.width,
             precision: self.precision,
-
-            // These only exist in the struct for the `run` method,
-            // which won’t be used together with this method.
-            curarg: self.curarg.clone(),
-            args: self.args,
-        }
-    }
-
-    // First up is the collection of functions used to execute a format string
-    // at runtime. This consumes all of the compile-time statics generated by
-    // the format! syntax extension.
-    fn run(&mut self, arg: &rt::v1::Argument) -> Result {
-        // Fill in the format parameters into the formatter
-        self.fill = arg.format.fill;
-        self.align = arg.format.align;
-        self.flags = arg.format.flags;
-        self.width = self.getcount(&arg.format.width);
-        self.precision = self.getcount(&arg.format.precision);
-
-        // Extract the correct argument
-        let value = match arg.position {
-            rt::v1::Position::Next => *self.curarg.next().unwrap(),
-            rt::v1::Position::At(i) => self.args[i],
-        };
-
-        // Then actually do some printing
-        (value.formatter)(value.value, self)
-    }
-
-    fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
-        match *cnt {
-            rt::v1::Count::Is(n) => Some(n),
-            rt::v1::Count::Implied => None,
-            rt::v1::Count::Param(i) => self.args[i].as_usize(),
-            rt::v1::Count::NextParam => self.curarg.next()?.as_usize(),
         }
     }
 
@@ -1244,12 +1237,15 @@
             // The sign and prefix goes before the padding if the fill character
             // is zero
             Some(min) if self.sign_aware_zero_pad() => {
-                self.fill = '0';
-                self.align = rt::v1::Alignment::Right;
+                let old_fill = crate::mem::replace(&mut self.fill, '0');
+                let old_align = crate::mem::replace(&mut self.align, rt::v1::Alignment::Right);
                 write_prefix(self, sign, prefix)?;
                 let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
                 self.buf.write_str(buf)?;
-                post_padding.write(self.buf)
+                post_padding.write(self.buf)?;
+                self.fill = old_fill;
+                self.align = old_align;
+                Ok(())
             }
             // Otherwise, the sign and prefix goes after the padding
             Some(min) => {
diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs
index 826ae36..fd81f932 100644
--- a/src/libcore/fmt/rt/v1.rs
+++ b/src/libcore/fmt/rt/v1.rs
@@ -7,7 +7,10 @@
 
 #[derive(Copy, Clone)]
 pub struct Argument {
+    #[cfg(bootstrap)]
     pub position: Position,
+    #[cfg(not(bootstrap))]
+    pub position: usize,
     pub format: FormatSpec,
 }
 
@@ -37,12 +40,11 @@
 pub enum Count {
     Is(usize),
     Param(usize),
-    NextParam,
     Implied,
 }
 
+#[cfg(bootstrap)]
 #[derive(Copy, Clone)]
 pub enum Position {
-    Next,
     At(usize),
 }
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index 6eb837e..5787b91 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1815,8 +1815,14 @@
     }
 
     #[inline]
-    fn count(self) -> usize {
-        self.iter.count().saturating_sub(self.n)
+    fn count(mut self) -> usize {
+        if self.n > 0 {
+            // nth(n) skips n+1
+            if self.iter.nth(self.n - 1).is_none() {
+                return 0;
+            }
+        }
+        self.iter.count()
     }
 
     #[inline]
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index a65d47c..25dfc57 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -208,6 +208,11 @@
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub struct Empty<T>(marker::PhantomData<T>);
 
+#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
+unsafe impl<T> Send for Empty<T> {}
+#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
+unsafe impl<T> Sync for Empty<T> {}
+
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
 impl<T> fmt::Debug for Empty<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index c958289..21a5698 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -2968,10 +2968,7 @@
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        match self.partial_cmp(other) {
-            Some(Ordering::Less) | Some(Ordering::Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Ordering::Less) | Some(Ordering::Equal))
     }
 
     /// Determines if the elements of this `Iterator` are lexicographically
@@ -3011,10 +3008,7 @@
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        match self.partial_cmp(other) {
-            Some(Ordering::Greater) | Some(Ordering::Equal) => true,
-            _ => false,
-        }
+        matches!(self.partial_cmp(other), Some(Ordering::Greater) | Some(Ordering::Equal))
     }
 
     /// Checks if the elements of this iterator are sorted.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 6f1d698..f77b4d7 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -44,7 +44,7 @@
 // Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
 // this, both the generated test artifact and the linked libtest (which
 // transitively includes libcore) will both define the same set of lang items,
-// and this will cause the E0152 "duplicate lang item found" error. See
+// and this will cause the E0152 "found duplicate lang item" error. See
 // discussion in #50466 for details.
 //
 // This cfg won't affect doc tests.
@@ -70,7 +70,7 @@
 #![feature(bound_cloned)]
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
-#![feature(const_fn)]
+#![feature(const_alloc_layout)]
 #![feature(const_if_match)]
 #![feature(const_panic)]
 #![feature(const_fn_union)]
@@ -133,7 +133,7 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs
index 3606448..4c3b81e 100644
--- a/src/libcore/mem/manually_drop.rs
+++ b/src/libcore/mem/manually_drop.rs
@@ -87,27 +87,28 @@
         slot.value
     }
 
-    /// Takes the contained value out.
+    /// Takes the value from the `ManuallyDrop<T>` container out.
     ///
     /// This method is primarily intended for moving out values in drop.
     /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
     /// you can use this method to take the value and use it however desired.
-    /// `Drop` will be invoked on the returned value following normal end-of-scope rules.
     ///
-    /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
+    /// Whenever possible, it is preferrable to use [`into_inner`][`ManuallyDrop::into_inner`]
+    /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
     ///
     /// # Safety
     ///
-    /// This function semantically moves out the contained value without preventing further usage.
-    /// It is up to the user of this method to ensure that this container is not used again.
+    /// This function semantically moves out the contained value without preventing further usage,
+    /// leaving the state of this container unchanged.
+    /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
     ///
     /// [`ManuallyDrop::drop`]: #method.drop
     /// [`ManuallyDrop::into_inner`]: #method.into_inner
     #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
-    #[unstable(feature = "manually_drop_take", issue = "55422")]
+    #[stable(feature = "manually_drop_take", since = "1.42.0")]
     #[inline]
     pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
-        ManuallyDrop::into_inner(ptr::read(slot))
+        ptr::read(&slot.value)
     }
 }
 
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index b6b4a46..072966a 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1416,6 +1416,7 @@
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             #[inline]
             pub const fn wrapping_abs(self) -> Self {
@@ -1709,6 +1710,7 @@
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             pub const fn overflowing_neg(self) -> (Self, bool) {
                 if self == Self::min_value() {
@@ -1997,6 +1999,7 @@
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             #[inline]
             #[rustc_inherit_overflow_checks]
@@ -4283,10 +4286,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_alphabetic(&self) -> bool {
-        match *self {
-            b'A'..=b'Z' | b'a'..=b'z' => true,
-            _ => false,
-        }
+        matches!(*self, b'A'..=b'Z' | b'a'..=b'z')
     }
 
     /// Checks if the value is an ASCII uppercase character:
@@ -4318,10 +4318,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_uppercase(&self) -> bool {
-        match *self {
-            b'A'..=b'Z' => true,
-            _ => false,
-        }
+        matches!(*self, b'A'..=b'Z')
     }
 
     /// Checks if the value is an ASCII lowercase character:
@@ -4353,10 +4350,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_lowercase(&self) -> bool {
-        match *self {
-            b'a'..=b'z' => true,
-            _ => false,
-        }
+        matches!(*self, b'a'..=b'z')
     }
 
     /// Checks if the value is an ASCII alphanumeric character:
@@ -4391,10 +4385,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_alphanumeric(&self) -> bool {
-        match *self {
-            b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' => true,
-            _ => false,
-        }
+        matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z')
     }
 
     /// Checks if the value is an ASCII decimal digit:
@@ -4426,10 +4417,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_digit(&self) -> bool {
-        match *self {
-            b'0'..=b'9' => true,
-            _ => false,
-        }
+        matches!(*self, b'0'..=b'9')
     }
 
     /// Checks if the value is an ASCII hexadecimal digit:
@@ -4464,10 +4452,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_hexdigit(&self) -> bool {
-        match *self {
-            b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f' => true,
-            _ => false,
-        }
+        matches!(*self, b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f')
     }
 
     /// Checks if the value is an ASCII punctuation character:
@@ -4503,10 +4488,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_punctuation(&self) -> bool {
-        match *self {
-            b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~' => true,
-            _ => false,
-        }
+        matches!(*self, b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~')
     }
 
     /// Checks if the value is an ASCII graphic character:
@@ -4538,10 +4520,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_graphic(&self) -> bool {
-        match *self {
-            b'!'..=b'~' => true,
-            _ => false,
-        }
+        matches!(*self, b'!'..=b'~')
     }
 
     /// Checks if the value is an ASCII whitespace character:
@@ -4590,10 +4569,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_whitespace(&self) -> bool {
-        match *self {
-            b'\t' | b'\n' | b'\x0C' | b'\r' | b' ' => true,
-            _ => false,
-        }
+        matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ')
     }
 
     /// Checks if the value is an ASCII control character:
@@ -4627,10 +4603,7 @@
     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
     #[inline]
     pub fn is_ascii_control(&self) -> bool {
-        match *self {
-            b'\0'..=b'\x1F' | b'\x7F' => true,
-            _ => false,
-        }
+        matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
     }
 }
 
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 2066a48..cb4247d 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -151,6 +151,7 @@
 
 /// The `Option` type. See [the module level documentation](index.html) for more.
 #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+#[rustc_diagnostic_item = "option_type"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Option<T> {
     /// No value
@@ -187,10 +188,7 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_some(&self) -> bool {
-        match *self {
-            Some(_) => true,
-            None => false,
-        }
+        matches!(*self, Some(_))
     }
 
     /// Returns `true` if the option is a [`None`] value.
@@ -341,6 +339,7 @@
     /// x.expect("the world is ending"); // panics with `the world is ending`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn expect(self, msg: &str) -> T {
         match self {
@@ -374,6 +373,7 @@
     /// assert_eq!(x.unwrap(), "air"); // fails
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap(self) -> T {
         match self {
@@ -1015,6 +1015,7 @@
     /// }
     /// ```
     #[inline]
+    #[track_caller]
     #[unstable(feature = "option_expect_none", reason = "newly added", issue = "62633")]
     pub fn expect_none(self, msg: &str) {
         if let Some(val) = self {
@@ -1057,6 +1058,7 @@
     /// }
     /// ```
     #[inline]
+    #[track_caller]
     #[unstable(feature = "option_unwrap_none", reason = "newly added", issue = "62633")]
     pub fn unwrap_none(self) {
         if let Some(val) = self {
@@ -1184,6 +1186,7 @@
 // This is a separate function to reduce the code size of .expect() itself.
 #[inline(never)]
 #[cold]
+#[track_caller]
 fn expect_failed(msg: &str) -> ! {
     panic!("{}", msg)
 }
@@ -1191,6 +1194,7 @@
 // This is a separate function to reduce the code size of .expect_none() itself.
 #[inline(never)]
 #[cold]
+#[track_caller]
 fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! {
     panic!("{}: {:?}", msg, value)
 }
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index aca6fb2..676d2c7 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -672,6 +672,7 @@
     #[stable(feature = "pin", since = "1.33.0")]
     pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
     where
+        U: ?Sized,
         F: FnOnce(&T) -> &U,
     {
         let pointer = &*self.pointer;
@@ -763,6 +764,7 @@
     #[stable(feature = "pin", since = "1.33.0")]
     pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U>
     where
+        U: ?Sized,
         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 d7b351f..c197686 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -169,22 +169,12 @@
 /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
 /// manually.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
-#[inline(always)]
-pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-    real_drop_in_place(&mut *to_drop)
-}
-
-// The real `drop_in_place` -- the one that gets called implicitly when variables go
-// out of scope -- should have a safe reference and not a raw pointer as argument
-// type.  When we drop a local variable, we access it with a pointer that behaves
-// like a safe reference; transmuting that to a raw pointer does not mean we can
-// actually access it with raw pointers.
 #[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
-unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     // Code here does not matter - this is replaced by the
     // real drop glue by the compiler.
-    real_drop_in_place(to_drop)
+    drop_in_place(to_drop)
 }
 
 /// Creates a null raw pointer.
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index b3bb2f1..4bc0a3e 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -250,6 +250,20 @@
     /// *first_value = 4;
     /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
     /// ```
+    ///
+    /// # Null-unchecked version
+    ///
+    /// If you are sure the pointer can never be null and are looking for some kind of
+    /// `as_mut_unchecked` that returns the `&mut T` instead of `Option<&mut T>`, know that
+    /// you can dereference the pointer directly.
+    ///
+    /// ```
+    /// let mut s = [1, 2, 3];
+    /// let ptr: *mut u32 = s.as_mut_ptr();
+    /// let first_value = unsafe { &mut *ptr };
+    /// *first_value = 4;
+    /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
+    /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 5cfc810..bc70dbd 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -242,6 +242,7 @@
 /// [`Err`]: enum.Result.html#variant.Err
 #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
 #[must_use = "this `Result` may be an `Err` variant, which should be handled"]
+#[rustc_diagnostic_item = "result_type"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Result<T, E> {
     /// Contains the success value
@@ -282,10 +283,7 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn is_ok(&self) -> bool {
-        match *self {
-            Ok(_) => true,
-            Err(_) => false,
-        }
+        matches!(*self, Ok(_))
     }
 
     /// Returns `true` if the result is [`Err`].
@@ -957,6 +955,7 @@
     /// x.unwrap(); // panics with `emergency failure`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap(self) -> T {
         match self {
@@ -984,6 +983,7 @@
     /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "result_expect", since = "1.4.0")]
     pub fn expect(self, msg: &str) -> T {
         match self {
@@ -1017,6 +1017,7 @@
     /// assert_eq!(x.unwrap_err(), "emergency failure");
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_err(self) -> E {
         match self {
@@ -1044,6 +1045,7 @@
     /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "result_expect_err", since = "1.17.0")]
     pub fn expect_err(self, msg: &str) -> E {
         match self {
@@ -1091,13 +1093,51 @@
     }
 }
 
+#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
+impl<T, E: Into<!>> Result<T, E> {
+    /// Unwraps a result that can never be an [`Err`], yielding the content of the [`Ok`].
+    ///
+    /// Unlike [`unwrap`], this method is known to never panic on the
+    /// result types it is implemented for. Therefore, it can be used
+    /// instead of `unwrap` as a maintainability safeguard that will fail
+    /// to compile if the error type of the `Result` is later changed
+    /// to an error that can actually occur.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    /// [`unwrap`]: enum.Result.html#method.unwrap
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// # #![feature(never_type)]
+    /// # #![feature(unwrap_infallible)]
+    ///
+    /// fn only_good_news() -> Result<String, !> {
+    ///     Ok("this is fine".into())
+    /// }
+    ///
+    /// let s: String = only_good_news().into_ok();
+    /// println!("{}", s);
+    /// ```
+    #[inline]
+    pub fn into_ok(self) -> T {
+        match self {
+            Ok(x) => x,
+            Err(e) => e.into(),
+        }
+    }
+}
+
 #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: Deref, E> Result<T, E> {
     /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
     ///
     /// Leaves the original `Result` in-place, creating a new one containing a reference to the
     /// `Ok` type's `Deref::Target` type.
-    pub fn as_deref_ok(&self) -> Result<&T::Target, &E> {
+    pub fn as_deref(&self) -> Result<&T::Target, &E> {
         self.as_ref().map(|t| t.deref())
     }
 }
@@ -1114,23 +1154,12 @@
 }
 
 #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T: Deref, E: Deref> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E::Target>`.
-    ///
-    /// Leaves the original `Result` in-place, creating a new one containing a reference to both
-    /// the `Ok` and `Err` types' `Deref::Target` types.
-    pub fn as_deref(&self) -> Result<&T::Target, &E::Target> {
-        self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
-    }
-}
-
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: DerefMut, E> Result<T, E> {
     /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T::Target, &mut E>`.
     ///
     /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
     /// the `Ok` type's `Deref::Target` type.
-    pub fn as_deref_mut_ok(&mut self) -> Result<&mut T::Target, &mut E> {
+    pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
         self.as_mut().map(|t| t.deref_mut())
     }
 }
@@ -1146,18 +1175,6 @@
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T: DerefMut, E: DerefMut> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to
-    /// `Result<&mut T::Target, &mut E::Target>`.
-    ///
-    /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
-    /// both the `Ok` and `Err` types' `Deref::Target` types.
-    pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target> {
-        self.as_mut().map(|t| t.deref_mut()).map_err(|e| e.deref_mut())
-    }
-}
-
 impl<T, E> Result<Option<T>, E> {
     /// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
     ///
@@ -1188,6 +1205,7 @@
 // This is a separate function to reduce the code size of the methods
 #[inline(never)]
 #[cold]
+#[track_caller]
 fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
     panic!("{}: {:?}", msg, error)
 }
diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs
index 8a1fb9d..88b2bc5 100644
--- a/src/libcore/str/lossy.rs
+++ b/src/libcore/str/lossy.rs
@@ -3,8 +3,6 @@
 use crate::mem;
 use crate::str as core_str;
 
-// ignore-tidy-undocumented-unsafe
-
 /// Lossy UTF-8 string.
 #[unstable(feature = "str_internals", issue = "none")]
 pub struct Utf8Lossy {
@@ -17,6 +15,7 @@
     }
 
     pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
+        // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required.
         unsafe { mem::transmute(bytes) }
     }
 
@@ -60,6 +59,8 @@
         while i < self.source.len() {
             let i_ = i;
 
+            // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and
+            // only increases, so `0 <= i < self.source.len()`.
             let byte = unsafe { *self.source.get_unchecked(i) };
             i += 1;
 
@@ -69,6 +70,7 @@
 
                 macro_rules! error {
                     () => {{
+                        // SAFETY: We have checked up to `i` that source is valid UTF-8.
                         unsafe {
                             let r = Utf8LossyChunk {
                                 valid: core_str::from_utf8_unchecked(&self.source[0..i_]),
@@ -130,6 +132,7 @@
         }
 
         let r = Utf8LossyChunk {
+            // SAFETY: We have checked that the entire source is valid UTF-8.
             valid: unsafe { core_str::from_utf8_unchecked(self.source) },
             broken: &[],
         };
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index ab771b1..5a7cddd 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1,5 +1,4 @@
 // ignore-tidy-filelength
-// ignore-tidy-undocumented-unsafe
 
 //! String manipulation.
 //!
@@ -341,6 +340,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     run_utf8_validation(v)?;
+    // SAFETY: Just ran validation.
     Ok(unsafe { from_utf8_unchecked(v) })
 }
 
@@ -379,6 +379,7 @@
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
     run_utf8_validation(v)?;
+    // SAFETY: Just ran validation.
     Ok(unsafe { from_utf8_unchecked_mut(v) })
 }
 
@@ -581,7 +582,7 @@
     #[inline]
     fn next(&mut self) -> Option<char> {
         next_code_point(&mut self.iter).map(|ch| {
-            // str invariant says `ch` is a valid Unicode Scalar Value
+            // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value.
             unsafe { char::from_u32_unchecked(ch) }
         })
     }
@@ -628,7 +629,7 @@
     #[inline]
     fn next_back(&mut self) -> Option<char> {
         next_code_point_reverse(&mut self.iter).map(|ch| {
-            // str invariant says `ch` is a valid Unicode Scalar Value
+            // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value.
             unsafe { char::from_u32_unchecked(ch) }
         })
     }
@@ -658,6 +659,7 @@
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     #[inline]
     pub fn as_str(&self) -> &'a str {
+        // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8.
         unsafe { from_utf8_unchecked(self.iter.as_slice()) }
     }
 }
@@ -1102,6 +1104,7 @@
     fn get_end(&mut self) -> Option<&'a str> {
         if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
             self.finished = true;
+            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
             unsafe {
                 let string = self.matcher.haystack().get_unchecked(self.start..self.end);
                 Some(string)
@@ -1119,6 +1122,7 @@
 
         let haystack = self.matcher.haystack();
         match self.matcher.next_match() {
+            // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries.
             Some((a, b)) => unsafe {
                 let elt = haystack.get_unchecked(self.start..a);
                 self.start = b;
@@ -1151,11 +1155,13 @@
 
         let haystack = self.matcher.haystack();
         match self.matcher.next_match_back() {
+            // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries.
             Some((a, b)) => unsafe {
                 let elt = haystack.get_unchecked(b..self.end);
                 self.end = a;
                 Some(elt)
             },
+            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
             None => unsafe {
                 self.finished = true;
                 Some(haystack.get_unchecked(self.start..self.end))
@@ -1297,6 +1303,7 @@
     fn next(&mut self) -> Option<(usize, &'a str)> {
         self.0
             .next_match()
+            // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
             .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
     }
 
@@ -1307,6 +1314,7 @@
     {
         self.0
             .next_match_back()
+            // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
             .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
     }
 }
@@ -1348,6 +1356,7 @@
 impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
+        // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
         self.0.next_match().map(|(a, b)| unsafe {
             // Indices are known to be on utf8 boundaries
             self.0.haystack().get_unchecked(a..b)
@@ -1359,6 +1368,7 @@
     where
         P::Searcher: ReverseSearcher<'a>,
     {
+        // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
         self.0.next_match_back().map(|(a, b)| unsafe {
             // Indices are known to be on utf8 boundaries
             self.0.haystack().get_unchecked(a..b)
@@ -1579,6 +1589,10 @@
             if align != usize::max_value() && align.wrapping_sub(index) % usize_bytes == 0 {
                 let ptr = v.as_ptr();
                 while index < blocks_end {
+                    // SAFETY: since `align - index` and `ascii_block_size` are
+                    // multiples of `usize_bytes`, `block = ptr.add(index)` is
+                    // always aligned with a `usize` so it's safe to dereference
+                    // both `block` and `block.offset(1)`.
                     unsafe {
                         let block = ptr.add(index) as *const usize;
                         // break if there is a nonascii byte
@@ -1804,6 +1818,7 @@
                 && slice.is_char_boundary(self.start)
                 && slice.is_char_boundary(self.end)
             {
+                // SAFETY: just checked that `start` and `end` are on a char boundary.
                 Some(unsafe { self.get_unchecked(slice) })
             } else {
                 None
@@ -1815,6 +1830,7 @@
                 && slice.is_char_boundary(self.start)
                 && slice.is_char_boundary(self.end)
             {
+                // SAFETY: just checked that `start` and `end` are on a char boundary.
                 Some(unsafe { self.get_unchecked_mut(slice) })
             } else {
                 None
@@ -1845,6 +1861,7 @@
                 && slice.is_char_boundary(self.start)
                 && slice.is_char_boundary(self.end)
             {
+                // SAFETY: just checked that `start` and `end` are on a char boundary.
                 unsafe { self.get_unchecked_mut(slice) }
             } else {
                 super::slice_error_fail(slice, self.start, self.end)
@@ -1873,6 +1890,7 @@
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
             if slice.is_char_boundary(self.end) {
+                // SAFETY: just checked that `end` is on a char boundary.
                 Some(unsafe { self.get_unchecked(slice) })
             } else {
                 None
@@ -1881,6 +1899,7 @@
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
             if slice.is_char_boundary(self.end) {
+                // SAFETY: just checked that `end` is on a char boundary.
                 Some(unsafe { self.get_unchecked_mut(slice) })
             } else {
                 None
@@ -1903,8 +1922,8 @@
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            // is_char_boundary checks that the index is in [0, .len()]
             if slice.is_char_boundary(self.end) {
+                // SAFETY: just checked that `end` is on a char boundary.
                 unsafe { self.get_unchecked_mut(slice) }
             } else {
                 super::slice_error_fail(slice, 0, self.end)
@@ -1934,6 +1953,7 @@
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
             if slice.is_char_boundary(self.start) {
+                // SAFETY: just checked that `start` is on a char boundary.
                 Some(unsafe { self.get_unchecked(slice) })
             } else {
                 None
@@ -1942,6 +1962,7 @@
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
             if slice.is_char_boundary(self.start) {
+                // SAFETY: just checked that `start` is on a char boundary.
                 Some(unsafe { self.get_unchecked_mut(slice) })
             } else {
                 None
@@ -1966,8 +1987,8 @@
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            // is_char_boundary checks that the index is in [0, .len()]
             if slice.is_char_boundary(self.start) {
+                // SAFETY: just checked that `start` is on a char boundary.
                 unsafe { self.get_unchecked_mut(slice) }
             } else {
                 super::slice_error_fail(slice, self.start, slice.len())
@@ -2238,7 +2259,6 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
     #[inline(always)]
-    // SAFETY: const sound because we transmute two types with the same layout
     #[allow(unused_attributes)]
     #[allow_internal_unstable(const_fn_union)]
     pub const fn as_bytes(&self) -> &[u8] {
@@ -2247,6 +2267,7 @@
             str: &'a str,
             slice: &'a [u8],
         }
+        // SAFETY: const sound because we transmute two types with the same layout
         unsafe { Slices { str: self }.slice }
     }
 
@@ -2573,6 +2594,7 @@
     pub fn split_at(&self, mid: usize) -> (&str, &str) {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
+            // SAFETY: just checked that `mid` is on a char boundary.
             unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) }
         } else {
             slice_error_fail(self, 0, mid)
@@ -2617,6 +2639,7 @@
         if self.is_char_boundary(mid) {
             let len = self.len();
             let ptr = self.as_mut_ptr();
+            // SAFETY: just checked that `mid` is on a char boundary.
             unsafe {
                 (
                     from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
@@ -3805,10 +3828,8 @@
         if let Some((_, b)) = matcher.next_reject_back() {
             j = b;
         }
-        unsafe {
-            // Searcher is known to return valid indices
-            self.get_unchecked(i..j)
-        }
+        // SAFETY: `Searcher` is known to return valid indices.
+        unsafe { self.get_unchecked(i..j) }
     }
 
     /// Returns a string slice with all prefixes that match a pattern
@@ -3844,10 +3865,8 @@
         if let Some((a, _)) = matcher.next_reject() {
             i = a;
         }
-        unsafe {
-            // Searcher is known to return valid indices
-            self.get_unchecked(i..self.len())
-        }
+        // SAFETY: `Searcher` is known to return valid indices.
+        unsafe { self.get_unchecked(i..self.len()) }
     }
 
     /// Returns a string slice with the prefix removed.
@@ -3878,10 +3897,8 @@
                 "The first search step from Searcher \
                 must include the first character"
             );
-            unsafe {
-                // Searcher is known to return valid indices.
-                Some(self.get_unchecked(len..))
-            }
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(self.get_unchecked(len..)) }
         } else {
             None
         }
@@ -3919,10 +3936,8 @@
                 "The first search step from ReverseSearcher \
                 must include the last character"
             );
-            unsafe {
-                // Searcher is known to return valid indices.
-                Some(self.get_unchecked(..start))
-            }
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(self.get_unchecked(..start)) }
         } else {
             None
         }
@@ -3970,10 +3985,8 @@
         if let Some((_, b)) = matcher.next_reject_back() {
             j = b;
         }
-        unsafe {
-            // Searcher is known to return valid indices
-            self.get_unchecked(0..j)
-        }
+        // SAFETY: `Searcher` is known to return valid indices.
+        unsafe { self.get_unchecked(0..j) }
     }
 
     /// Returns a string slice with all prefixes that match a pattern
@@ -4166,6 +4179,7 @@
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     pub fn make_ascii_uppercase(&mut self) {
+        // SAFETY: safe because we transmute two types with the same layout.
         let me = unsafe { self.as_bytes_mut() };
         me.make_ascii_uppercase()
     }
@@ -4191,6 +4205,7 @@
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     pub fn make_ascii_lowercase(&mut self) {
+        // SAFETY: safe because we transmute two types with the same layout.
         let me = unsafe { self.as_bytes_mut() };
         me.make_ascii_lowercase()
     }
@@ -4357,6 +4372,7 @@
 impl Default for &mut str {
     /// Creates an empty mutable str
     fn default() -> Self {
+        // SAFETY: The empty string is valid UTF-8.
         unsafe { from_utf8_unchecked_mut(&mut []) }
     }
 }
@@ -4412,6 +4428,7 @@
 
     #[derive(Clone)]
     struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
+        // SAFETY: not safe
         unsafe { from_utf8_unchecked(bytes) }
     };
 }
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 2cbdeb2..ef64d8b 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -3,8 +3,6 @@
 //! For more details, see the traits [`Pattern`], [`Searcher`],
 //! [`ReverseSearcher`], and [`DoubleEndedSearcher`].
 
-// ignore-tidy-undocumented-unsafe
-
 #![unstable(
     feature = "pattern",
     reason = "API not fully fleshed out and ready to be stabilized",
@@ -46,10 +44,7 @@
     /// Checks whether the pattern matches at the front of the haystack
     #[inline]
     fn is_prefix_of(self, haystack: &'a str) -> bool {
-        match self.into_searcher(haystack).next() {
-            SearchStep::Match(0, _) => true,
-            _ => false,
-        }
+        matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
     }
 
     /// Checks whether the pattern matches at the back of the haystack
@@ -58,10 +53,7 @@
     where
         Self::Searcher: ReverseSearcher<'a>,
     {
-        match self.into_searcher(haystack).next_back() {
-            SearchStep::Match(_, j) if haystack.len() == j => true,
-            _ => false,
-        }
+        matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
     }
 }
 
@@ -277,6 +269,14 @@
     #[inline]
     fn next(&mut self) -> SearchStep {
         let old_finger = self.finger;
+        // SAFETY: 1-4 guarantee safety of `get_unchecked`
+        // 1. `self.finger` and `self.finger_back` are kept on unicode boundaries
+        //    (this is invariant)
+        // 2. `self.finger >= 0` since it starts at 0 and only increases
+        // 3. `self.finger < self.finger_back` because otherwise the char `iter`
+        //    would return `SearchStep::Done`
+        // 4. `self.finger` comes before the end of the haystack because `self.finger_back`
+        //    starts at the end and only decreases
         let slice = unsafe { self.haystack.get_unchecked(old_finger..self.finger_back) };
         let mut iter = slice.chars();
         let old_len = iter.iter.len();
@@ -299,6 +299,7 @@
             // get the haystack after the last character found
             let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?;
             // the last byte of the utf8 encoded needle
+            // SAFETY: we have an invariant that `utf8_size < 5`
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
             if let Some(index) = memchr::memchr(last_byte, bytes) {
                 // The new finger is the index of the byte we found,
@@ -342,6 +343,7 @@
     #[inline]
     fn next_back(&mut self) -> SearchStep {
         let old_finger = self.finger_back;
+        // SAFETY: see the comment for next() above
         let slice = unsafe { self.haystack.get_unchecked(self.finger..old_finger) };
         let mut iter = slice.chars();
         let old_len = iter.iter.len();
@@ -369,6 +371,7 @@
                 return None;
             };
             // the last byte of the utf8 encoded needle
+            // SAFETY: we have an invariant that `utf8_size < 5`
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
             if let Some(index) = memchr::memrchr(last_byte, bytes) {
                 // we searched a slice that was offset by self.finger,
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index a2352c0..9d449bb 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -112,8 +112,6 @@
 //! println!("live threads: {}", old_thread_count + 1);
 //! ```
 
-// ignore-tidy-undocumented-unsafe
-
 #![stable(feature = "rust1", since = "1.0.0")]
 #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
 #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
@@ -134,16 +132,10 @@
 /// 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.
 ///
-/// 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.
+/// A common use case for `spin_loop_hint` is implementing bounded optimistic spinning in a CAS
+/// loop in synchronization primitives. To avoid problems like priority inversion, it is strongly
+/// recommended that the spin loop is terminated after a finite amount of iterations and an
+/// appropriate blocking syscall is made.
 ///
 /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
 /// do anything at all.
@@ -356,6 +348,7 @@
     #[inline]
     #[stable(feature = "atomic_access", since = "1.15.0")]
     pub fn get_mut(&mut self) -> &mut bool {
+        // SAFETY: the mutable reference guarantees unique ownership.
         unsafe { &mut *(self.v.get() as *mut bool) }
     }
 
@@ -406,6 +399,8 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> bool {
+        // SAFETY: any data races are prevented by atomic intrinsics and the raw
+        // pointer passed in is valid because we got it from a reference.
         unsafe { atomic_load(self.v.get(), order) != 0 }
     }
 
@@ -438,6 +433,8 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, val: bool, order: Ordering) {
+        // SAFETY: any data races are prevented by atomic intrinsics and the raw
+        // pointer passed in is valid because we got it from a reference.
         unsafe {
             atomic_store(self.v.get(), val as u8, order);
         }
@@ -469,6 +466,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn swap(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -564,6 +562,7 @@
         success: Ordering,
         failure: Ordering,
     ) -> Result<bool, bool> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         match unsafe {
             atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure)
         } {
@@ -621,6 +620,7 @@
         success: Ordering,
         failure: Ordering,
     ) -> Result<bool, bool> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         match unsafe {
             atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure)
         } {
@@ -667,6 +667,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -762,6 +763,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -803,6 +805,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -878,6 +881,7 @@
     #[inline]
     #[stable(feature = "atomic_access", since = "1.15.0")]
     pub fn get_mut(&mut self) -> &mut *mut T {
+        // SAFETY: the mutable reference guarantees unique ownership.
         unsafe { &mut *self.p.get() }
     }
 
@@ -929,6 +933,7 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> *mut T {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T }
     }
 
@@ -963,6 +968,7 @@
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe {
             atomic_store(self.p.get() as *mut usize, ptr as usize, order);
         }
@@ -996,6 +1002,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "ptr")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
     }
 
@@ -1080,6 +1087,7 @@
         success: Ordering,
         failure: Ordering,
     ) -> Result<*mut T, *mut T> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe {
             let res = atomic_compare_exchange(
                 self.p.get() as *mut usize,
@@ -1143,6 +1151,7 @@
         success: Ordering,
         failure: Ordering,
     ) -> Result<*mut T, *mut T> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe {
             let res = atomic_compare_exchange_weak(
                 self.p.get() as *mut usize,
@@ -1296,6 +1305,7 @@
                 #[inline]
                 #[$stable_access]
                 pub fn get_mut(&mut self) -> &mut $int_type {
+                    // SAFETY: the mutable reference guarantees unique ownership.
                     unsafe { &mut *self.v.get() }
                 }
             }
@@ -1350,6 +1360,7 @@
                 #[inline]
                 #[$stable]
                 pub fn load(&self, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_load(self.v.get(), order) }
                 }
             }
@@ -1384,6 +1395,7 @@
                 #[inline]
                 #[$stable]
                 pub fn store(&self, val: $int_type, order: Ordering) {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_store(self.v.get(), val, order); }
                 }
             }
@@ -1414,6 +1426,7 @@
                 #[$stable]
                 #[$cfg_cas]
                 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_swap(self.v.get(), val, order) }
                 }
             }
@@ -1516,6 +1529,7 @@
                                         new: $int_type,
                                         success: Ordering,
                                         failure: Ordering) -> Result<$int_type, $int_type> {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
                 }
             }
@@ -1568,6 +1582,7 @@
                                              new: $int_type,
                                              success: Ordering,
                                              failure: Ordering) -> Result<$int_type, $int_type> {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe {
                         atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
                     }
@@ -1602,6 +1617,7 @@
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_add(self.v.get(), val, order) }
                 }
             }
@@ -1634,6 +1650,7 @@
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_sub(self.v.get(), val, order) }
                 }
             }
@@ -1669,6 +1686,7 @@
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_and(self.v.get(), val, order) }
                 }
             }
@@ -1705,6 +1723,7 @@
                 #[$stable_nand]
                 #[$cfg_cas]
                 pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_nand(self.v.get(), val, order) }
                 }
             }
@@ -1740,6 +1759,7 @@
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_or(self.v.get(), val, order) }
                 }
             }
@@ -1775,6 +1795,7 @@
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_xor(self.v.get(), val, order) }
                 }
             }
@@ -1886,6 +1907,7 @@
                        issue = "48655")]
                 #[$cfg_cas]
                 pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { $max_fn(self.v.get(), val, order) }
                 }
             }
@@ -1938,6 +1960,7 @@
                        issue = "48655")]
                 #[$cfg_cas]
                 pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { $min_fn(self.v.get(), val, order) }
                 }
             }
@@ -1966,7 +1989,9 @@
 }
 
 let mut atomic = ", stringify!($atomic_type), "::new(1);
-unsafe {
+",
+// SAFETY: Safe as long as `my_atomic_op` is atomic.
+"unsafe {
     my_atomic_op(atomic.as_mut_ptr());
 }
 # }
@@ -2532,6 +2557,7 @@
     // https://github.com/WebAssembly/tool-conventions/issues/59. We should
     // follow that discussion and implement a solution when one comes about!
     #[cfg(not(target_arch = "wasm32"))]
+    // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
             Acquire => intrinsics::atomic_fence_acq(),
@@ -2619,6 +2645,7 @@
 #[inline]
 #[stable(feature = "compiler_fences", since = "1.21.0")]
 pub fn compiler_fence(order: Ordering) {
+    // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
             Acquire => intrinsics::atomic_singlethreadfence_acq(),
diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs
index d567ae5..b3a4bd2 100644
--- a/src/libcore/task/poll.rs
+++ b/src/libcore/task/poll.rs
@@ -39,10 +39,7 @@
     #[inline]
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn is_ready(&self) -> bool {
-        match *self {
-            Poll::Ready(_) => true,
-            Poll::Pending => false,
-        }
+        matches!(*self, Poll::Ready(_))
     }
 
     /// Returns `true` if this is `Poll::Pending`
diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs
index 90a9bcc..129c121 100644
--- a/src/libcore/tests/fmt/builders.rs
+++ b/src/libcore/tests/fmt/builders.rs
@@ -93,6 +93,91 @@
             format!("{:#?}", Bar)
         );
     }
+
+    #[test]
+    fn test_only_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo { .. }", format!("{:?}", Foo));
+        assert_eq!(
+            "Foo {
+    ..
+}",
+            format!("{:#?}", Foo)
+        );
+    }
+
+    #[test]
+    fn test_multiple_and_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo { bar: true, baz: 10/20, .. }", format!("{:?}", Foo));
+        assert_eq!(
+            "Foo {
+    bar: true,
+    baz: 10/20,
+    ..
+}",
+            format!("{:#?}", Foo)
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Bar")
+                    .field("foo", &Foo)
+                    .field("hello", &"world")
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(
+            "Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }",
+            format!("{:?}", Bar)
+        );
+        assert_eq!(
+            "Bar {
+    foo: Foo {
+        bar: true,
+        baz: 10/20,
+        ..
+    },
+    hello: \"world\",
+    ..
+}",
+            format!("{:#?}", Bar)
+        );
+    }
 }
 
 mod debug_tuple {
diff --git a/src/libcore/tests/fmt/mod.rs b/src/libcore/tests/fmt/mod.rs
index d86e21c..7b281ce 100644
--- a/src/libcore/tests/fmt/mod.rs
+++ b/src/libcore/tests/fmt/mod.rs
@@ -28,3 +28,18 @@
     assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
     assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
 }
+
+#[test]
+fn pad_integral_resets() {
+    struct Bar;
+
+    impl core::fmt::Display for Bar {
+        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+            "1".fmt(f)?;
+            f.pad_integral(true, "", "5")?;
+            "1".fmt(f)
+        }
+    }
+
+    assert_eq!(format!("{:<03}", Bar), "1  0051  ");
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 39f6133..f042024 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -5,6 +5,7 @@
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(debug_map_key_value)]
+#![feature(debug_non_exhaustive)]
 #![feature(dec2flt)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
@@ -18,7 +19,7 @@
 #![feature(range_is_empty)]
 #![feature(raw)]
 #![feature(saturating_neg)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
 #![feature(specialization)]
@@ -31,7 +32,6 @@
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(int_error_matching)]
-#![feature(const_fn)]
 #![feature(array_value_iter)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
@@ -40,6 +40,8 @@
 #![feature(slice_from_raw_parts)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_raw_ptr_deref)]
+#![feature(never_type)]
+#![feature(unwrap_infallible)]
 
 extern crate test;
 
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index 499a561..c835313 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -184,6 +184,28 @@
 }
 
 #[test]
+pub fn test_into_ok() {
+    fn infallible_op() -> Result<isize, !> {
+        Ok(666)
+    }
+
+    assert_eq!(infallible_op().into_ok(), 666);
+
+    enum MyNeverToken {}
+    impl From<MyNeverToken> for ! {
+        fn from(never: MyNeverToken) -> ! {
+            match never {}
+        }
+    }
+
+    fn infallible_op2() -> Result<isize, MyNeverToken> {
+        Ok(667)
+    }
+
+    assert_eq!(infallible_op2().into_ok(), 667);
+}
+
+#[test]
 fn test_try() {
     fn try_result_some() -> Option<u8> {
         let val = Ok(1)?;
@@ -214,32 +236,18 @@
 
 #[test]
 fn test_result_as_deref() {
-    // &Result<T: Deref, E>::Ok(T).as_deref_ok() ->
+    // &Result<T: Deref, E>::Ok(T).as_deref() ->
     //      Result<&T::Deref::Target, &E>::Ok(&*T)
     let ref_ok = &Result::Ok::<&i32, u8>(&42);
     let expected_result = Result::Ok::<&i32, &u8>(&42);
-    assert_eq!(ref_ok.as_deref_ok(), expected_result);
+    assert_eq!(ref_ok.as_deref(), expected_result);
 
     let ref_ok = &Result::Ok::<String, u32>(String::from("a result"));
     let expected_result = Result::Ok::<&str, &u32>("a result");
-    assert_eq!(ref_ok.as_deref_ok(), expected_result);
+    assert_eq!(ref_ok.as_deref(), expected_result);
 
     let ref_ok = &Result::Ok::<Vec<i32>, u32>(vec![1, 2, 3, 4, 5]);
     let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
-    assert_eq!(ref_ok.as_deref_ok(), expected_result);
-
-    // &Result<T: Deref, E: Deref>::Ok(T).as_deref() ->
-    //      Result<&T::Deref::Target, &E::Deref::Target>::Ok(&*T)
-    let ref_ok = &Result::Ok::<&i32, &u8>(&42);
-    let expected_result = Result::Ok::<&i32, &u8>(&42);
-    assert_eq!(ref_ok.as_deref(), expected_result);
-
-    let ref_ok = &Result::Ok::<String, &u32>(String::from("a result"));
-    let expected_result = Result::Ok::<&str, &u32>("a result");
-    assert_eq!(ref_ok.as_deref(), expected_result);
-
-    let ref_ok = &Result::Ok::<Vec<i32>, &u32>(vec![1, 2, 3, 4, 5]);
-    let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
     assert_eq!(ref_ok.as_deref(), expected_result);
 
     // &Result<T, E: Deref>::Err(T).as_deref_err() ->
@@ -259,19 +267,21 @@
     // &Result<T: Deref, E: Deref>::Err(T).as_deref_err() ->
     //      Result<&T, &E::Deref::Target>::Err(&*E)
     let ref_err = &Result::Err::<&u8, &i32>(&41);
-    let expected_result = Result::Err::<&u8, &i32>(&41);
+    let expected_result = Result::Err::<&u8, &&i32>(&&41);
     assert_eq!(ref_err.as_deref(), expected_result);
 
-    let ref_err = &Result::Err::<&u32, String>(String::from("an error"));
-    let expected_result = Result::Err::<&u32, &str>("an error");
+    let s = String::from("an error");
+    let ref_err = &Result::Err::<&u32, String>(s.clone());
+    let expected_result = Result::Err::<&u32, &String>(&s);
     assert_eq!(ref_err.as_deref(), expected_result);
 
-    let ref_err = &Result::Err::<&u32, Vec<i32>>(vec![5, 4, 3, 2, 1]);
-    let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice());
+    let v = vec![5, 4, 3, 2, 1];
+    let ref_err = &Result::Err::<&u32, Vec<i32>>(v.clone());
+    let expected_result = Result::Err::<&u32, &Vec<i32>>(&v);
     assert_eq!(ref_err.as_deref(), expected_result);
 
     // The following cases test calling `as_deref_*` with the wrong variant (i.e.
-    // `as_deref_ok()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`.
+    // `as_deref()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`.
     // While uncommon, these cases are supported to ensure that an `as_deref_*`
     // call can still be made even when one of the Result types does not implement
     // `Deref` (for example, std::io::Error).
@@ -290,57 +300,39 @@
     let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]);
     assert_eq!(ref_ok.as_deref_err(), expected_result);
 
-    // &Result<T: Deref, E>::Err(E).as_deref_ok() ->
+    // &Result<T: Deref, E>::Err(E).as_deref() ->
     //      Result<&T::Deref::Target, &E>::Err(&E)
     let ref_err = &Result::Err::<&u8, i32>(41);
     let expected_result = Result::Err::<&u8, &i32>(&41);
-    assert_eq!(ref_err.as_deref_ok(), expected_result);
+    assert_eq!(ref_err.as_deref(), expected_result);
 
     let ref_err = &Result::Err::<&u32, &str>("an error");
     let expected_result = Result::Err::<&u32, &&str>(&"an error");
-    assert_eq!(ref_err.as_deref_ok(), expected_result);
+    assert_eq!(ref_err.as_deref(), expected_result);
 
     let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]);
     let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]);
-    assert_eq!(ref_err.as_deref_ok(), expected_result);
+    assert_eq!(ref_err.as_deref(), expected_result);
 }
 
 #[test]
 fn test_result_as_deref_mut() {
-    // &mut Result<T: Deref, E>::Ok(T).as_deref_mut_ok() ->
+    // &mut Result<T: Deref, E>::Ok(T).as_deref_mut() ->
     //      Result<&mut T::Deref::Target, &mut E>::Ok(&mut *T)
     let mut val = 42;
     let mut expected_val = 42;
     let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val);
     let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
-    assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_ok.as_deref_mut(), expected_result);
 
     let mut expected_string = String::from("a result");
     let mut_ok = &mut Result::Ok::<String, u32>(expected_string.clone());
     let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
-    assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_ok.as_deref_mut(), expected_result);
 
     let mut expected_vec = vec![1, 2, 3, 4, 5];
     let mut_ok = &mut Result::Ok::<Vec<i32>, u32>(expected_vec.clone());
     let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
-    assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
-
-    // &mut Result<T: Deref, E: Deref>::Ok(T).as_deref_mut() ->
-    //      Result<&mut T::Deref::Target, &mut E::Deref::Target>::Ok(&mut *T)
-    let mut val = 42;
-    let mut expected_val = 42;
-    let mut_ok = &mut Result::Ok::<&mut i32, &mut u8>(&mut val);
-    let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
-    assert_eq!(mut_ok.as_deref_mut(), expected_result);
-
-    let mut expected_string = String::from("a result");
-    let mut_ok = &mut Result::Ok::<String, &mut u32>(expected_string.clone());
-    let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
-    assert_eq!(mut_ok.as_deref_mut(), expected_result);
-
-    let mut expected_vec = vec![1, 2, 3, 4, 5];
-    let mut_ok = &mut Result::Ok::<Vec<i32>, &mut u32>(expected_vec.clone());
-    let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
     assert_eq!(mut_ok.as_deref_mut(), expected_result);
 
     // &mut Result<T, E: Deref>::Err(T).as_deref_mut_err() ->
@@ -364,23 +356,22 @@
     // &mut Result<T: Deref, E: Deref>::Err(T).as_deref_mut_err() ->
     //      Result<&mut T, &mut E::Deref::Target>::Err(&mut *E)
     let mut val = 41;
-    let mut expected_val = 41;
-    let mut_err = &mut Result::Err::<&mut u8, &mut i32>(&mut val);
-    let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
+    let mut_err = &mut Result::Err::<&mut u8, i32>(val);
+    let expected_result = Result::Err::<&mut u8, &mut i32>(&mut val);
     assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let mut expected_string = String::from("an error");
     let mut_err = &mut Result::Err::<&mut u32, String>(expected_string.clone());
-    let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.as_mut_str());
+    let expected_result = Result::Err::<&mut u32, &mut String>(&mut expected_string);
     assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let mut expected_vec = vec![5, 4, 3, 2, 1];
     let mut_err = &mut Result::Err::<&mut u32, Vec<i32>>(expected_vec.clone());
-    let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice());
+    let expected_result = Result::Err::<&mut u32, &mut Vec<i32>>(&mut expected_vec);
     assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     // The following cases test calling `as_deref_mut_*` with the wrong variant (i.e.
-    // `as_deref_mut_ok()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`.
+    // `as_deref_mut()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`.
     // While uncommon, these cases are supported to ensure that an `as_deref_mut_*`
     // call can still be made even when one of the Result types does not implement
     // `Deref` (for example, std::io::Error).
@@ -404,22 +395,22 @@
     let expected_result = Result::Ok::<&mut [i32; 5], &mut u32>(&mut expected_arr);
     assert_eq!(mut_ok.as_deref_mut_err(), expected_result);
 
-    // &mut Result<T: Deref, E>::Err(E).as_deref_mut_ok() ->
+    // &mut Result<T: Deref, E>::Err(E).as_deref_mut() ->
     //      Result<&mut T::Deref::Target, &mut E>::Err(&mut E)
     let mut expected_val = 41;
     let mut_err = &mut Result::Err::<&mut u8, i32>(expected_val.clone());
     let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
-    assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let string = String::from("an error");
     let expected_string = string.clone();
     let mut ref_str = expected_string.as_ref();
     let mut_err = &mut Result::Err::<&mut u32, &str>(string.as_str());
     let expected_result = Result::Err::<&mut u32, &mut &str>(&mut ref_str);
-    assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_err.as_deref_mut(), expected_result);
 
     let mut expected_arr = [5, 4, 3, 2, 1];
     let mut_err = &mut Result::Err::<&mut u32, [i32; 5]>(expected_arr.clone());
     let expected_result = Result::Err::<&mut u32, &mut [i32; 5]>(&mut expected_arr);
-    assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
+    assert_eq!(mut_err.as_deref_mut(), expected_result);
 }
diff --git a/src/libcore/unicode/bool_trie.rs b/src/libcore/unicode/bool_trie.rs
deleted file mode 100644
index b7fba88..0000000
--- a/src/libcore/unicode/bool_trie.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-/// BoolTrie is a trie for representing a set of Unicode codepoints. It is
-/// implemented with postfix compression (sharing of identical child nodes),
-/// which gives both compact size and fast lookup.
-///
-/// The space of Unicode codepoints is divided into 3 subareas, each
-/// represented by a trie with different depth. In the first (0..0x800), there
-/// is no trie structure at all; each u64 entry corresponds to a bitvector
-/// effectively holding 64 bool values.
-///
-/// In the second (0x800..0x10000), each child of the root node represents a
-/// 64-wide subrange, but instead of storing the full 64-bit value of the leaf,
-/// the trie stores an 8-bit index into a shared table of leaf values. This
-/// exploits the fact that in reasonable sets, many such leaves can be shared.
-///
-/// In the third (0x10000..0x110000), each child of the root node represents a
-/// 4096-wide subrange, and the trie stores an 8-bit index into a 64-byte slice
-/// of a child tree. Each of these 64 bytes represents an index into the table
-/// of shared 64-bit leaf values. This exploits the sparse structure in the
-/// non-BMP range of most Unicode sets.
-pub struct BoolTrie {
-    // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences)
-    pub r1: [u64; 32], // leaves
-
-    // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences)
-    pub r2: [u8; 992],      // first level
-    pub r3: &'static [u64], // leaves
-
-    // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences)
-    pub r4: [u8; 256],      // first level
-    pub r5: &'static [u8],  // second level
-    pub r6: &'static [u64], // leaves
-}
-impl BoolTrie {
-    pub fn lookup(&self, c: char) -> bool {
-        let c = c as u32;
-        if c < 0x800 {
-            trie_range_leaf(c, self.r1[(c >> 6) as usize])
-        } else if c < 0x10000 {
-            let child = self.r2[(c >> 6) as usize - 0x20];
-            trie_range_leaf(c, self.r3[child as usize])
-        } else {
-            let child = self.r4[(c >> 12) as usize - 0x10];
-            let leaf = self.r5[((child as usize) << 6) + ((c >> 6) as usize & 0x3f)];
-            trie_range_leaf(c, self.r6[leaf as usize])
-        }
-    }
-}
-
-pub struct SmallBoolTrie {
-    pub(crate) r1: &'static [u8],  // first level
-    pub(crate) r2: &'static [u64], // leaves
-}
-
-impl SmallBoolTrie {
-    pub fn lookup(&self, c: char) -> bool {
-        let c = c as u32;
-        match self.r1.get((c >> 6) as usize) {
-            Some(&child) => trie_range_leaf(c, self.r2[child as usize]),
-            None => false,
-        }
-    }
-}
-
-fn trie_range_leaf(c: u32, bitmap_chunk: u64) -> bool {
-    ((bitmap_chunk >> (c & 63)) & 1) != 0
-}
diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs
index e424174..b6eaf06 100644
--- a/src/libcore/unicode/mod.rs
+++ b/src/libcore/unicode/mod.rs
@@ -1,15 +1,59 @@
 #![unstable(feature = "unicode_internals", issue = "none")]
 #![allow(missing_docs)]
 
-mod bool_trie;
 pub(crate) mod printable;
-pub(crate) mod tables;
+mod unicode_data;
 pub(crate) mod version;
 
+use version::UnicodeVersion;
+
+/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
+/// `char` and `str` methods are based on.
+#[unstable(feature = "unicode_version", issue = "49726")]
+pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
+    major: unicode_data::UNICODE_VERSION.0,
+    minor: unicode_data::UNICODE_VERSION.1,
+    micro: unicode_data::UNICODE_VERSION.2,
+    _priv: (),
+};
+
 // For use in liballoc, not re-exported in libstd.
 pub mod derived_property {
-    pub use crate::unicode::tables::derived_property::{Case_Ignorable, Cased};
+    pub use super::{Case_Ignorable, Cased};
 }
-pub mod conversions {
-    pub use crate::unicode::tables::conversions::{to_lower, to_upper};
+
+pub use unicode_data::alphabetic::lookup as Alphabetic;
+pub use unicode_data::case_ignorable::lookup as Case_Ignorable;
+pub use unicode_data::cased::lookup as Cased;
+pub use unicode_data::cc::lookup as Cc;
+pub use unicode_data::conversions;
+pub use unicode_data::grapheme_extend::lookup as Grapheme_Extend;
+pub use unicode_data::lowercase::lookup as Lowercase;
+pub use unicode_data::n::lookup as N;
+pub use unicode_data::uppercase::lookup as Uppercase;
+pub use unicode_data::white_space::lookup as White_Space;
+
+#[inline(always)]
+fn range_search<const N: usize, const N1: usize, const N2: usize>(
+    needle: u32,
+    chunk_idx_map: &[u8; N],
+    (last_chunk_idx, last_chunk_mapping): (u16, u8),
+    bitset_chunk_idx: &[[u8; 16]; N1],
+    bitset: &[u64; N2],
+) -> bool {
+    let bucket_idx = (needle / 64) as usize;
+    let chunk_map_idx = bucket_idx / 16;
+    let chunk_piece = bucket_idx % 16;
+    let chunk_idx = if chunk_map_idx >= N {
+        if chunk_map_idx == last_chunk_idx as usize {
+            last_chunk_mapping
+        } else {
+            return false;
+        }
+    } else {
+        chunk_idx_map[chunk_map_idx]
+    };
+    let idx = bitset_chunk_idx[(chunk_idx as usize)][chunk_piece];
+    let word = bitset[(idx as usize)];
+    (word & (1 << (needle % 64) as u64)) != 0
 }
diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs
deleted file mode 100644
index 3fa125e..0000000
--- a/src/libcore/unicode/tables.rs
+++ /dev/null
@@ -1,2235 +0,0 @@
-// NOTE: The following code was generated by "./unicode.py", do not edit directly
-
-#![allow(missing_docs, non_upper_case_globals, non_snake_case, clippy::unreadable_literal)]
-
-use crate::unicode::bool_trie::{BoolTrie, SmallBoolTrie};
-use crate::unicode::version::UnicodeVersion;
-
-/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
-/// `char` and `str` methods are based on.
-#[unstable(feature = "unicode_version", issue = "49726")]
-pub const UNICODE_VERSION: UnicodeVersion =
-    UnicodeVersion { major: 12, minor: 1, micro: 0, _priv: () };
-pub(crate) mod general_category {
-    #[rustfmt::skip]
-    const Cc_table: &super::SmallBoolTrie = &super::SmallBoolTrie {
-        r1: &[
-            0, 1, 0
-        ],
-        r2: &[
-            0x00000000ffffffff, 0x8000000000000000
-        ],
-    };
-
-    pub fn Cc(c: char) -> bool {
-        Cc_table.lookup(c)
-    }
-
-    #[rustfmt::skip]
-    const N_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x03ff000000000000, 0x0000000000000000, 0x720c000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x000003ff00000000, 0x0000000000000000, 0x03ff000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00000000000003ff
-        ],
-        r2: [
-            0, 0, 0, 0, 0, 1, 0, 2, 0, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0, 1, 0, 6, 0, 1, 0, 7, 0, 7, 8,
-            0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 11, 0, 0, 0, 12, 7, 0, 0, 0, 0, 13, 0, 14, 0, 0, 15, 0, 0, 7, 16, 0, 0, 15, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 9, 0, 0, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 27, 0, 28,
-            29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,
-            0, 0, 1, 0, 0, 0, 0, 31, 0, 0, 7, 9, 0, 0, 32, 0, 7, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0
-        ],
-        r3: &[
-            0x0000000000000000, 0x0000ffc000000000, 0x03f0ffc000000000, 0x00fcffc000000000,
-            0x0007ffc000000000, 0x7f00ffc000000000, 0x01ffffc07f000000, 0x0000000003ff0000,
-            0x000fffff00000000, 0x00000000000003ff, 0x1ffffe0000000000, 0x0001c00000000000,
-            0x03ff03ff00000000, 0x000000000000ffc0, 0x0000000007ff0000, 0x0000000003ff03ff,
-            0x03ff000000000000, 0x03f1000000000000, 0xffffffffffff0000, 0x00000000000003e7,
-            0xffffffff00000000, 0x000000000fffffff, 0xfffffc0000000000, 0xffc0000000000000,
-            0x00000000000fffff, 0x2000000000000000, 0x070003fe00000080, 0x00000000003c0000,
-            0x000003ff00000000, 0x00000000fffeff00, 0xfffe0000000003ff, 0x003f000000000000,
-            0x03ff000003ff0000
-        ],
-        r4: [
-            0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 7, 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, 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
-        ],
-        r5: &[
-            0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 9, 10, 11, 12, 0, 13, 14, 0, 15, 16, 17, 0, 18, 19, 0, 0, 0, 0, 20, 21, 0,
-            0, 0, 0, 22, 0, 0, 23, 24, 0, 0, 0, 25, 0, 21, 26, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 0, 0,
-            28, 0, 28, 0, 0, 0, 0, 0, 28, 0, 29, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 32, 0, 0, 0, 28, 8, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 39, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 21,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 28, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 42, 43, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0
-        ],
-        r6: &[
-            0x0000000000000000, 0x000fffffffffff80, 0x01ffffffffffffff, 0x0000000000000c00,
-            0x0ffffffe00000000, 0x0000000f00000000, 0x0000000000000402, 0x00000000003e0000,
-            0x000003ff00000000, 0xfe000000ff000000, 0x0000ff8000000000, 0xf800000000000000,
-            0x000000000fc00000, 0x3000000000000000, 0xfffffffffffcffff, 0x60000000000001ff,
-            0x00000000e0000000, 0x0000f80000000000, 0xff000000ff000000, 0x0000fe0000000000,
-            0xfc00000000000000, 0x03ff000000000000, 0x7fffffff00000000, 0x0000007fe0000000,
-            0x00000000001e0000, 0x0000fffffffc0000, 0xffc0000000000000, 0x001ffffe03ff0000,
-            0x0000000003ff0000, 0x00000000000003ff, 0x0fff000000000000, 0x0007ffff00000000,
-            0x00001fffffff0000, 0x00000000001fffff, 0xffffffffffffffff, 0x00007fffffffffff,
-            0x00000003fbff0000, 0x00000000007fffff, 0x000fffff00000000, 0x01ffffff00000000,
-            0xffffffffffffc000, 0x000000000000ff80, 0xfffe000000000000, 0x001eefffffffffff,
-            0x3fffbffffffffffe, 0x0000000000001fff
-        ],
-    };
-
-    pub fn N(c: char) -> bool {
-        N_table.lookup(c)
-    }
-}
-
-pub(crate) mod derived_property {
-    #[rustfmt::skip]
-    const Alphabetic_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3,
-            0x0000000000000000, 0xbcdf000000000020, 0xfffffffbffffd740, 0xffbfffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff,
-            0xfffeffffffffffff, 0xffffffff027fffff, 0xbfff0000000001ff, 0x000787ffffff00b6,
-            0xffffffff07ff0000, 0xffffc000feffffff, 0xffffffffffffffff, 0x9c00e1fe1fefffff,
-            0xffffffffffff0000, 0xffffffffffffe000, 0x0003ffffffffffff, 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, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 37, 38, 39, 40, 41,
-            42, 43, 44, 36, 36, 36, 36, 36, 36, 36, 36, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-            56, 57, 58, 59, 60, 61, 62, 31, 63, 64, 65, 66, 67, 68, 69, 70, 36, 36, 36, 71, 36, 36,
-            36, 36, 72, 73, 74, 75, 31, 76, 77, 31, 78, 79, 80, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 81, 82, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 83, 84, 36, 85, 86, 87, 88, 89, 90, 31, 31, 31,
-            31, 31, 31, 31, 91, 44, 92, 93, 94, 36, 95, 96, 31, 31, 31, 31, 31, 31, 31, 31, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 55, 31, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 97, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 98, 99, 36, 36, 36, 36, 100, 101, 36, 97, 102, 36, 103,
-            104, 105, 106, 36, 107, 108, 109, 110, 111, 67, 112, 113, 114, 115, 116, 36, 117, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 118, 119,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            36, 36, 36, 36, 36, 120, 36, 121, 122, 123, 124, 125, 36, 36, 36, 36, 126, 33, 127, 128,
-            31, 129, 36, 130, 131, 132, 113, 133
-        ],
-        r3: &[
-            0x00001ffffcffffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000,
-            0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x1003000fb080599f,
-            0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x1e00000f00011bbf,
-            0xe3edfdfffff99fee, 0x0002000fb0c0199f, 0xc3ffc718d63dc7ec, 0x0000000000811dc7,
-            0xe3fffdfffffddfef, 0x0000000f07601ddf, 0xe3effdfffffddfef, 0x0006000f40601ddf,
-            0xe7fffffffffddfef, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f,
-            0x07fffffffffffffe, 0x000000000000207f, 0x3bffffaffffff7d6, 0x00000000f000205f,
-            0x0000000000000001, 0xfffe1ffffffffeff, 0x1ffffffffeffff03, 0x0000000000000000,
-            0xf97fffffffffffff, 0xffffffffffff0000, 0xffffffff3c00ffff, 0xf7ffffffffff20bf,
-            0xffffffffffffffff, 0xffffffff3d7f3dff, 0x7f3dffffffff3dff, 0xffffffffff7fff3d,
-            0xffffffffff3dffff, 0x0000000007ffffff, 0xffffffff0000ffff, 0x3f3fffffffffffff,
-            0xfffffffffffffffe, 0xffff9fffffffffff, 0xffffffff07fffffe, 0x01ffc7ffffffffff,
-            0x000fffff000fdfff, 0x000ddfff000fffff, 0xffcfffffffffffff, 0x00000000108001ff,
-            0xffffffff00000000, 0x01ffffffffffffff, 0xffff07ffffffffff, 0x003fffffffffffff,
-            0x01ff0fff7fffffff, 0x001f3fffffff0000, 0xffff0fffffffffff, 0x00000000000003ff,
-            0xffffffff0fffffff, 0x001ffffe7fffffff, 0x0000008000000000, 0xffefffffffffffff,
-            0x0000000000000fef, 0xfc00f3ffffffffff, 0x0003ffbfffffffff, 0x007fffffffffffff,
-            0x3ffffffffc00e000, 0xe7ffffffffff01ff, 0x046fde0000000000, 0x001fff8000000000,
-            0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc,
-            0x8002000000000000, 0x000000001fff0000, 0xf3ffbd503e2ffc84, 0xffffffff000043e0,
-            0x00000000000001ff, 0xffc0000000000000, 0x000003ffffffffff, 0xffff7fffffffffff,
-            0xffffffff7fffffff, 0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff,
-            0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x0000800000000000, 0x1f3e03fe000000e0,
-            0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffeffffffffffe0, 0x07ffffff00007fff,
-            0xffff000000000000, 0x0000ffffffffffff, 0x0000000000001fff, 0x3fffffffffff0000,
-            0x00000c00ffff1fff, 0x8ff07fffffffffff, 0xfffffffcff800000, 0xfffffffffffff9ff,
-            0xff8000000000007c, 0x000000ffffffffbf, 0x000fffffffffffff, 0xe8fc00000000002f,
-            0xffff07fffffffc00, 0x1fffffff0007ffff, 0xfff7ffffffffffff, 0x7c00ffff00008000,
-            0xfc7fffff00003fff, 0x7fffffffffffffff, 0x003cffff38000005, 0xffff7f7f007e7e7e,
-            0xffff00fff7ffffff, 0x000007ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f,
-            0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb,
-            0x0003ffffffffffff, 0xfffffffffff80000, 0x3fffffffffffffff, 0xfffffffffffcffff,
-            0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, 0x07fffffe00000000,
-            0xffffffc007fffffe, 0x000000001cfcfcfc
-        ],
-        r4: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 14,
-            15, 7, 16, 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, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 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, 33, 4, 4, 4, 4, 4, 4, 4, 34, 35, 4, 36, 2, 35, 37, 38, 32, 39, 2, 40, 41, 4, 42, 43,
-            44, 45, 4, 4, 2, 46, 2, 47, 4, 4, 48, 49, 50, 51, 52, 4, 53, 4, 4, 4, 54, 4, 55, 56, 4,
-            4, 57, 58, 59, 60, 61, 54, 4, 4, 4, 4, 62, 63, 64, 4, 65, 66, 67, 4, 4, 4, 4, 36, 4, 4,
-            4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 68, 4, 2, 69, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 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, 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, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 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, 54, 20, 4, 72, 73, 74, 75, 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, 95, 4, 4, 4, 96, 97, 4, 4, 4, 4, 4, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 99, 2, 100, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 101, 102, 103, 4, 4, 4, 4, 4, 4, 4, 4, 4, 104, 105, 106, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 107, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 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, 108, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 109, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 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,
-            110, 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, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f,
-            0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff,
-            0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff,
-            0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff,
-            0x003ffffffeeff06f, 0x1fffffff00000000, 0x000000001fffffff, 0x0000001ffffffeff,
-            0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff,
-            0x0007ffffffffffff, 0x000000ffffffffff, 0xffff00801fffffff, 0x000000000000003f,
-            0x007fffff00000000, 0x01fffffffffffffc, 0x000001ffffff0000, 0x0047ffffffff0070,
-            0x000000001400001e, 0x409ffffffffbffff, 0xffff01ffbfffbd7f, 0x000001ffffffffff,
-            0xe3edfdfffff99fef, 0x0000000fe081199f, 0x00000000800007bb, 0x00000000000000b3,
-            0x7f3fffffffffffff, 0x000000003f000000, 0x7fffffffffffffff, 0x0000000000000011,
-            0x013fffffffffffff, 0x000007ffe7ffffff, 0x01ffffffffffffff, 0xffffffff00000000,
-            0x80000000ffffffff, 0xfffffcff00000000, 0x0000001afcffffff, 0x7fe7ffffffffffff,
-            0xffffffffffff0000, 0x0000000020ffffff, 0x7f7ffffffffffdff, 0xfffc000000000001,
-            0x007ffefffffcffff, 0xb47ffffffffffb7f, 0xfffffdbf000000cb, 0x00000000017b7fff,
-            0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f,
-            0x00003fffffff0000, 0x0000ffffffffffff, 0xe0fffff80000000f, 0x000000000000ffff,
-            0xffffffffffff87ff, 0x00000000ffff80ff, 0x0000000b00000000, 0x00ffffffffffffff,
-            0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000043ff01ff,
-            0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf,
-            0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff,
-            0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000007dbf9ffff7f,
-            0x3f801fffffffffff, 0x0000000000004000, 0x00000fffffffffff, 0x000000000000001f,
-            0x000000000000088f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff,
-            0xffff000000000000, 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff,
-            0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff
-        ],
-    };
-
-    pub fn Alphabetic(c: char) -> bool {
-        Alphabetic_table.lookup(c)
-    }
-
-    #[rustfmt::skip]
-    const Case_Ignorable_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0400408000000000, 0x0000000140000000, 0x0190a10000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0xffff000000000000, 0xffffffffffffffff,
-            0xffffffffffffffff, 0x0430ffffffffffff, 0x00000000000000b0, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x00000000000003f8, 0x0000000000000000,
-            0x0000000000000000, 0x0000000002000000, 0xbffffffffffe0000, 0x00100000000000b6,
-            0x0000000017ff003f, 0x00010000fffff801, 0x0000000000000000, 0x00003dffbfc00000,
-            0xffff000000028000, 0x00000000000007ff, 0x0001ffc000000000, 0x243ff80000000000
-        ],
-        r2: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 10, 11, 12, 13, 14, 15, 16, 11, 17, 18, 19, 2, 20, 21,
-            22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 34, 35, 36, 37, 38, 39, 40, 2, 41, 2, 2, 2, 42, 43, 44, 2,
-            45, 46, 47, 48, 49, 50, 2, 51, 52, 53, 54, 55, 2, 2, 2, 2, 2, 2, 56, 57, 58, 59, 60, 61,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 2, 63, 2, 64, 2, 65, 66, 2, 2, 2, 2,
-            2, 2, 2, 67, 2, 68, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 50, 2, 2, 2, 2, 71, 72, 73, 74, 75, 76, 77, 78, 79, 2, 2, 80, 81,
-            82, 83, 84, 85, 86, 87, 88, 2, 89, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 2, 92, 93, 2, 2, 2, 2, 2, 2, 2, 2, 94, 95, 2, 96,
-            97, 98, 99, 100
-        ],
-        r3: &[
-            0x00003fffffc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffffffff80000,
-            0x1400000000000007, 0x0002000c00fe21fe, 0x1000000000000002, 0x4000000c0000201e,
-            0x1000000000000006, 0x0023000000023986, 0xfc00000c000021be, 0x9000000000000002,
-            0x0000000c0040201e, 0x0000000000000004, 0x0000000000002001, 0xc000000000000011,
-            0x0000000c00603dc1, 0x0000000c00003040, 0x1800000000000003, 0x0000000c0000201e,
-            0x00000000005c0400, 0x07f2000000000000, 0x0000000000007fc0, 0x1ff2000000000000,
-            0x0000000000003f40, 0x02a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df,
-            0x0000000000000040, 0x66fde00000000000, 0x001e0001c3000000, 0x0000000020002064,
-            0x1000000000000000, 0x00000000e0000000, 0x001c0000001c0000, 0x000c0000000c0000,
-            0x3fb0000000000000, 0x00000000208ffe40, 0x0000000000007800, 0x0000000000000008,
-            0x0000020000000060, 0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000,
-            0x7fff008000000000, 0x17d000000000000f, 0x000ff80000000004, 0x00003b3c00000003,
-            0x0003a34000000000, 0x00cff00000000000, 0x3f00000000000000, 0x031021fdfff70000,
-            0xfffff00000000000, 0x010007ffffffffff, 0xfffffffff8000000, 0xfbffffffffffffff,
-            0xa000000000000000, 0x6000e000e000e003, 0x00007c900300f800, 0x8002ffdf00000000,
-            0x000000001fff0000, 0x0001ffffffff0000, 0x3000000000000000, 0x0003800000000000,
-            0x8000800000000000, 0xffffffff00000000, 0x0000800000000000, 0x083e3c0000000020,
-            0x000000007e000000, 0x7000000000000000, 0x0000000000200000, 0x0000000000001000,
-            0xbff7800000000000, 0x00000000f0000000, 0x0003000000000000, 0x00000003ffffffff,
-            0x0001000000000000, 0x0000000000000700, 0x0300000000000000, 0x0000006000000844,
-            0x8003ffff00000030, 0x00003fc000000000, 0x000000000003ff80, 0x33c8000000000007,
-            0x0000006000008000, 0x00667e0000000000, 0x1001000000001008, 0xc19d000000000000,
-            0x0058300020000002, 0x00000000f8000000, 0x0000212000000000, 0x0000000040000000,
-            0xfffc000000000000, 0x0000000000000003, 0x0000ffff0008ffff, 0x0000000000240000,
-            0x8000000000000000, 0x4000000004004080, 0x0001000000000001, 0x00000000c0000000,
-            0x0e00000800000000
-        ],
-        r4: [
-            0, 1, 2, 3, 2, 2, 4, 2, 2, 2, 2, 5, 2, 6, 7, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-        ],
-        r5: &[
-            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
-            0, 0, 0, 7, 0, 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 17, 18, 19, 0, 0, 20, 21, 22,
-            23, 0, 0, 24, 25, 26, 27, 28, 0, 29, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 32, 33, 34, 0,
-            0, 0, 0, 0, 35, 0, 36, 0, 37, 38, 39, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 43, 44, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 50, 0, 0,
-            51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 52, 53, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0,
-            0, 0, 56, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 58, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 62, 0, 0, 62, 62, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-        ],
-        r6: &[
-            0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000,
-            0x870000000000f06e, 0x0000006000000000, 0x000000f000000000, 0x000000000001ffc0,
-            0xff00000000000002, 0x800000000000007f, 0x2678000000000003, 0x0000000000002000,
-            0x001fef8000000007, 0x0008000000000000, 0x7fc0000000000003, 0x0000000000001e00,
-            0x40d3800000000000, 0x000007f880000000, 0x1800000000000003, 0x001f1fc000000001,
-            0xff00000000000000, 0x000000004000005c, 0x85f8000000000000, 0x000000000000000d,
-            0xb03c000000000000, 0x0000000030000001, 0xa7f8000000000000, 0x0000000000000001,
-            0x00bf280000000000, 0x00000fbce0000000, 0x06ff800000000000, 0x000000010cf00000,
-            0x79f80000000007fe, 0x000000000e7e0080, 0x00000000037ffc00, 0xbf7f000000000000,
-            0x006dfcfffffc0000, 0xb47e000000000000, 0x00000000000000bf, 0x0000000000a30000,
-            0x0018000000000000, 0x01ff000000000000, 0x001f000000000000, 0x007f000000000000,
-            0x000000000000000f, 0x0000000000008000, 0x00000000ffff8000, 0x0000000b00000000,
-            0x0000000f60000000, 0xfff8038000000000, 0x00003c0000000fe7, 0x000000000000001c,
-            0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f,
-            0x3fff000000000000, 0x0000f00000000000, 0x00000000007f0000, 0x0000000000000ff0,
-            0xf800000000000000, 0xffffffff00000002, 0xffffffffffffffff, 0x0000ffffffffffff
-        ],
-    };
-
-    pub fn Case_Ignorable(c: char) -> bool {
-        Case_Ignorable_table.lookup(c)
-    }
-
-    #[rustfmt::skip]
-    const Cased_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xf7ffffffffffffff, 0xfffffffffffffff0,
-            0xffffffffffffffff, 0xffffffffffffffff, 0x01ffffffffefffff, 0x0000001f00000003,
-            0x0000000000000000, 0xbccf000000000020, 0xfffffffbffffd740, 0xffbfffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff,
-            0xfffeffffffffffff, 0xffffffff007fffff, 0x00000000000001ff, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
-        ],
-        r2: [
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 5, 5,
-            0, 5, 5, 5, 5, 6, 7, 8, 9, 0, 10, 11, 0, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 17, 18, 5, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22,
-            0, 23, 5, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, 5, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 29, 30, 0, 0
-        ],
-        r3: &[
-            0x0000000000000000, 0xffffffff00000000, 0xe7ffffffffff20bf, 0x3f3fffffffffffff,
-            0xe7ffffffffff01ff, 0xffffffffffffffff, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f,
-            0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000,
-            0xf21fbd503e2ffc84, 0xffffffff000043e0, 0x0000000000000018, 0xffc0000000000000,
-            0x000003ffffffffff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff,
-            0x000020bfffffffff, 0x00003fffffffffff, 0x000000003fffffff, 0xfffffffc00000000,
-            0xffffffffffff78ff, 0x070000000000007c, 0xffff000000000000, 0xffff00fff7ffffff,
-            0x0000000000f8007f, 0x07fffffe00000000, 0x0000000007fffffe
-        ],
-        r4: [
-            0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-        ],
-        r5: &[
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 9, 10, 11, 12, 1, 1, 1, 1, 13, 14, 15, 16, 17,
-            18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-        ],
-        r6: &[
-            0x0000000000000000, 0xffffffffffffffff, 0x000000000000ffff, 0xffff000000000000,
-            0x0fffffffff0fffff, 0x0007ffffffffffff, 0xffffffff00000000, 0x00000000ffffffff,
-            0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf,
-            0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff,
-            0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000000f,
-            0xffff03ffffff03ff, 0x00000000000003ff
-        ],
-    };
-
-    pub fn Cased(c: char) -> bool {
-        Cased_table.lookup(c)
-    }
-
-    #[rustfmt::skip]
-    const Grapheme_Extend_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0xffffffffffffffff, 0x0000ffffffffffff, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x00000000000003f8, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0xbffffffffffe0000, 0x00000000000000b6,
-            0x0000000007ff0000, 0x00010000fffff800, 0x0000000000000000, 0x00003d9f9fc00000,
-            0xffff000000020000, 0x00000000000007ff, 0x0001ffc000000000, 0x200ff80000000000
-        ],
-        r2: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 2, 21, 22,
-            23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 34, 35, 36, 37, 38, 2, 39, 2, 40, 2, 2, 2, 41, 42, 43, 2, 44,
-            45, 46, 47, 48, 2, 2, 49, 2, 2, 2, 50, 2, 2, 2, 2, 2, 2, 2, 2, 51, 2, 2, 52, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 2, 54, 2, 55, 2, 2, 2, 2, 2, 2, 2, 2, 56,
-            2, 57, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 58, 59, 60, 2, 2, 2, 2, 61, 2, 2, 62, 63, 64, 65, 66, 67, 68,
-            69, 70, 2, 2, 2, 71, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 72, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 73, 2, 2, 2, 2, 2, 59, 2
-        ],
-        r3: &[
-            0x00003eeffbc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffffbfff80000,
-            0x1400000000000007, 0x0000000c00fe21fe, 0x5000000000000002, 0x4000000c0080201e,
-            0x1000000000000006, 0x0023000000023986, 0xfc00000c000021be, 0xd000000000000002,
-            0x0000000c00c0201e, 0x4000000000000004, 0x0000000000802001, 0xc000000000000011,
-            0x0000000c00603dc1, 0x9000000000000002, 0x0000000c00603044, 0x5800000000000003,
-            0x0000000c0080201e, 0x00000000805c8400, 0x07f2000000000000, 0x0000000000007f80,
-            0x1ff2000000000000, 0x0000000000003f00, 0x02a0000003000000, 0x7ffe000000000000,
-            0x1ffffffffeffe0df, 0x0000000000000040, 0x66fde00000000000, 0x001e0001c3000000,
-            0x0000000020002064, 0x00000000e0000000, 0x001c0000001c0000, 0x000c0000000c0000,
-            0x3fb0000000000000, 0x00000000200ffe40, 0x0000000000003800, 0x0000020000000060,
-            0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000, 0x7fff000000000000,
-            0x17f000000000000f, 0x000ff80000000004, 0x00003b3c00000003, 0x0003a34000000000,
-            0x00cff00000000000, 0x031021fdfff70000, 0xfbffffffffffffff, 0x0000000000001000,
-            0x0001ffffffff0000, 0x0003800000000000, 0x8000000000000000, 0xffffffff00000000,
-            0x0000fc0000000000, 0x0000000006000000, 0x3ff7800000000000, 0x00000000c0000000,
-            0x0003000000000000, 0x0000006000000844, 0x8003ffff00000030, 0x00003fc000000000,
-            0x000000000003ff80, 0x33c8000000000007, 0x0000002000000000, 0x00667e0000000000,
-            0x1000000000001008, 0xc19d000000000000, 0x0040300000000002, 0x0000212000000000,
-            0x0000000040000000, 0x0000ffff0000ffff
-        ],
-        r4: [
-            0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 4, 2, 5, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-        ],
-        r5: &[
-            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
-            0, 0, 0, 7, 0, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 0, 0, 16, 17, 18, 0, 0, 19, 20, 21,
-            22, 0, 0, 23, 24, 25, 26, 27, 0, 28, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 30, 31, 32, 33, 0,
-            0, 0, 0, 0, 34, 0, 35, 0, 36, 37, 38, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 42, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 46, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 50, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 41, 0, 0, 0, 0, 0,
-            0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 54,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 56, 0,
-            0, 56, 56, 56, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0
-        ],
-        r6: &[
-            0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000,
-            0x870000000000f06e, 0x0000006000000000, 0x000000f000000000, 0x000000000001ffc0,
-            0xff00000000000002, 0x800000000000007f, 0x0678000000000003, 0x001fef8000000007,
-            0x0008000000000000, 0x7fc0000000000003, 0x0000000000001e00, 0x40d3800000000000,
-            0x000007f880000000, 0x5800000000000003, 0x001f1fc000800001, 0xff00000000000000,
-            0x000000004000005c, 0xa5f9000000000000, 0x000000000000000d, 0xb03c800000000000,
-            0x0000000030000001, 0xa7f8000000000000, 0x0000000000000001, 0x00bf280000000000,
-            0x00000fbce0000000, 0x06ff800000000000, 0x000000010cf00000, 0x79f80000000007fe,
-            0x000000000e7e0080, 0x00000000037ffc00, 0xbf7f000000000000, 0x006dfcfffffc0000,
-            0xb47e000000000000, 0x00000000000000bf, 0x0000000000a30000, 0x0018000000000000,
-            0x001f000000000000, 0x007f000000000000, 0x0000000000008000, 0x0000000000078000,
-            0x0000000060000000, 0xf807c3a000000000, 0x00003c0000000fe7, 0x000000000000001c,
-            0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f,
-            0x0000f00000000000, 0x00000000007f0000, 0x00000000000007f0, 0xffffffff00000000,
-            0xffffffffffffffff, 0x0000ffffffffffff
-        ],
-    };
-
-    pub fn Grapheme_Extend(c: char) -> bool {
-        Grapheme_Extend_table.lookup(c)
-    }
-
-    #[rustfmt::skip]
-    const Lowercase_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0000000000000000, 0x07fffffe00000000, 0x0420040000000000, 0xff7fffff80000000,
-            0x55aaaaaaaaaaaaaa, 0xd4aaaaaaaaaaab55, 0xe6512d2a4e243129, 0xaa29aaaab5555240,
-            0x93faaaaaaaaaaaaa, 0xffffffffffffaa85, 0x01ffffffffefffff, 0x0000001f00000003,
-            0x0000000000000000, 0x3c8a000000000020, 0xfffff00000010000, 0x192faaaaaae37fff,
-            0xffff000000000000, 0xaaaaaaaaffffffff, 0xaaaaaaaaaaaaa802, 0xaaaaaaaaaaaad554,
-            0x0000aaaaaaaaaaaa, 0xffffffff00000000, 0x00000000000001ff, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
-        ],
-        r2: [
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4, 4, 4,
-            0, 5, 5, 6, 5, 7, 8, 9, 10, 0, 11, 12, 0, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 17, 18, 5, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22,
-            0, 23, 24, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 27, 4, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0
-        ],
-        r3: &[
-            0x0000000000000000, 0xe7ffffffffff0000, 0x3f00000000000000, 0x00000000000001ff,
-            0xffffffffffffffff, 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaabfeaaaaa, 0x00ff00ff003f00ff,
-            0x3fff00ff00ff003f, 0x40df00ff00ff00ff, 0x00dc00ff00cf00dc, 0x8002000000000000,
-            0x000000001fff0000, 0x321080000008c400, 0xffff0000000043c0, 0x0000000000000010,
-            0x000003ffffff0000, 0xffff000000000000, 0x3fda15627fffffff, 0x0008501aaaaaaaaa,
-            0x000020bfffffffff, 0x00002aaaaaaaaaaa, 0x000000003aaaaaaa, 0xaaabaaa800000000,
-            0x95ffaaaaaaaaaaaa, 0xaaa082aaaaba50aa, 0x0700000000000008, 0xffff00fff7ffffff,
-            0x0000000000f8007f, 0x0000000007fffffe
-        ],
-        r4: [
-            0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 4, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-        ],
-        r5: &[
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-            21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-        ],
-        r6: &[
-            0x0000000000000000, 0xffffff0000000000, 0x000000000000ffff, 0x0fffffffff000000,
-            0x0007ffffffffffff, 0x00000000ffffffff, 0xffffffff00000000, 0x000ffffffc000000,
-            0x000000ffffdfc000, 0xebc000000ffffffc, 0xfffffc000000ffef, 0x00ffffffc000000f,
-            0x00000ffffffc0000, 0xfc000000ffffffc0, 0xffffc000000fffff, 0x0ffffffc000000ff,
-            0x0000ffffffc00000, 0x0000003ffffffc00, 0xf0000003f7fffffc, 0xffc000000fdfffff,
-            0xffff0000003f7fff, 0xfffffc000000fdff, 0x0000000000000bf7, 0xfffffffc00000000,
-            0x000000000000000f
-        ],
-    };
-
-    pub fn Lowercase(c: char) -> bool {
-        Lowercase_table.lookup(c)
-    }
-
-    #[rustfmt::skip]
-    const Uppercase_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0000000000000000, 0x0000000007fffffe, 0x0000000000000000, 0x000000007f7fffff,
-            0xaa55555555555555, 0x2b555555555554aa, 0x11aed2d5b1dbced6, 0x55d255554aaaa490,
-            0x6c05555555555555, 0x000000000000557a, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x8045000000000000, 0x00000ffbfffed740, 0xe6905555551c8000,
-            0x0000ffffffffffff, 0x5555555500000000, 0x5555555555555401, 0x5555555555552aab,
-            0xfffe555555555555, 0x00000000007fffff, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
-            0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
-        ],
-        r2: [
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
-            0, 5, 5, 6, 5, 7, 8, 9, 10, 0, 0, 0, 0, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
-            15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            16, 17, 5, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0,
-            21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 25, 0, 0, 0
-        ],
-        r3: &[
-            0x0000000000000000, 0xffffffff00000000, 0x00000000000020bf, 0x003fffffffffffff,
-            0xe7ffffffffff0000, 0x5555555555555555, 0x5555555540155555, 0xff00ff003f00ff00,
-            0x0000ff00aa003f00, 0x0f00000000000000, 0x0f001f000f000f00, 0xc00f3d503e273884,
-            0x0000ffff00000020, 0x0000000000000008, 0xffc0000000000000, 0x000000000000ffff,
-            0x00007fffffffffff, 0xc025ea9d00000000, 0x0004280555555555, 0x0000155555555555,
-            0x0000000005555555, 0x5554555400000000, 0x6a00555555555555, 0x555f7d5555452855,
-            0x0000000000000074, 0x07fffffe00000000
-        ],
-        r4: [
-            0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
-        ],
-        r5: &[
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-            21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-        ],
-        r6: &[
-            0x0000000000000000, 0x000000ffffffffff, 0xffff000000000000, 0x00000000000fffff,
-            0x0007ffffffffffff, 0xffffffff00000000, 0x00000000ffffffff, 0xfff0000003ffffff,
-            0xffffff0000003fff, 0x003fde64d0000003, 0x000003ffffff0000, 0x7b0000001fdfe7b0,
-            0xfffff0000001fc5f, 0x03ffffff0000003f, 0x00003ffffff00000, 0xf0000003ffffff00,
-            0xffff0000003fffff, 0xffffff00000003ff, 0x07fffffc00000001, 0x001ffffff0000000,
-            0x00007fffffc00000, 0x000001ffffff0000, 0x0000000000000400, 0x00000003ffffffff,
-            0xffff03ffffff03ff, 0x00000000000003ff
-        ],
-    };
-
-    pub fn Uppercase(c: char) -> bool {
-        Uppercase_table.lookup(c)
-    }
-}
-
-pub(crate) mod property {
-    #[rustfmt::skip]
-    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,
-            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, 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, 4, 5, 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, 0x0000000100000020, 0x0000000000000001,
-            0x00008300000007ff, 0x0000000080000000
-        ],
-    };
-
-    pub fn White_Space(c: char) -> bool {
-        White_Space_table.lookup(c)
-    }
-}
-
-pub(crate) mod conversions {
-    pub fn to_lower(c: char) -> [char; 3] {
-        match bsearch_case_table(c, to_lowercase_table) {
-            None => [c, '\0', '\0'],
-            Some(index) => to_lowercase_table[index].1,
-        }
-    }
-
-    pub fn to_upper(c: char) -> [char; 3] {
-        match bsearch_case_table(c, to_uppercase_table) {
-            None => [c, '\0', '\0'],
-            Some(index) => to_uppercase_table[index].1,
-        }
-    }
-
-    fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
-        table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
-    }
-
-    #[rustfmt::skip]
-    const to_lowercase_table: &[(char, [char; 3])] = &[
-        ('\u{41}', ['\u{61}', '\0', '\0']), ('\u{42}', ['\u{62}', '\0', '\0']), ('\u{43}',
-        ['\u{63}', '\0', '\0']), ('\u{44}', ['\u{64}', '\0', '\0']), ('\u{45}', ['\u{65}', '\0',
-        '\0']), ('\u{46}', ['\u{66}', '\0', '\0']), ('\u{47}', ['\u{67}', '\0', '\0']), ('\u{48}',
-        ['\u{68}', '\0', '\0']), ('\u{49}', ['\u{69}', '\0', '\0']), ('\u{4a}', ['\u{6a}', '\0',
-        '\0']), ('\u{4b}', ['\u{6b}', '\0', '\0']), ('\u{4c}', ['\u{6c}', '\0', '\0']), ('\u{4d}',
-        ['\u{6d}', '\0', '\0']), ('\u{4e}', ['\u{6e}', '\0', '\0']), ('\u{4f}', ['\u{6f}', '\0',
-        '\0']), ('\u{50}', ['\u{70}', '\0', '\0']), ('\u{51}', ['\u{71}', '\0', '\0']), ('\u{52}',
-        ['\u{72}', '\0', '\0']), ('\u{53}', ['\u{73}', '\0', '\0']), ('\u{54}', ['\u{74}', '\0',
-        '\0']), ('\u{55}', ['\u{75}', '\0', '\0']), ('\u{56}', ['\u{76}', '\0', '\0']), ('\u{57}',
-        ['\u{77}', '\0', '\0']), ('\u{58}', ['\u{78}', '\0', '\0']), ('\u{59}', ['\u{79}', '\0',
-        '\0']), ('\u{5a}', ['\u{7a}', '\0', '\0']), ('\u{c0}', ['\u{e0}', '\0', '\0']), ('\u{c1}',
-        ['\u{e1}', '\0', '\0']), ('\u{c2}', ['\u{e2}', '\0', '\0']), ('\u{c3}', ['\u{e3}', '\0',
-        '\0']), ('\u{c4}', ['\u{e4}', '\0', '\0']), ('\u{c5}', ['\u{e5}', '\0', '\0']), ('\u{c6}',
-        ['\u{e6}', '\0', '\0']), ('\u{c7}', ['\u{e7}', '\0', '\0']), ('\u{c8}', ['\u{e8}', '\0',
-        '\0']), ('\u{c9}', ['\u{e9}', '\0', '\0']), ('\u{ca}', ['\u{ea}', '\0', '\0']), ('\u{cb}',
-        ['\u{eb}', '\0', '\0']), ('\u{cc}', ['\u{ec}', '\0', '\0']), ('\u{cd}', ['\u{ed}', '\0',
-        '\0']), ('\u{ce}', ['\u{ee}', '\0', '\0']), ('\u{cf}', ['\u{ef}', '\0', '\0']), ('\u{d0}',
-        ['\u{f0}', '\0', '\0']), ('\u{d1}', ['\u{f1}', '\0', '\0']), ('\u{d2}', ['\u{f2}', '\0',
-        '\0']), ('\u{d3}', ['\u{f3}', '\0', '\0']), ('\u{d4}', ['\u{f4}', '\0', '\0']), ('\u{d5}',
-        ['\u{f5}', '\0', '\0']), ('\u{d6}', ['\u{f6}', '\0', '\0']), ('\u{d8}', ['\u{f8}', '\0',
-        '\0']), ('\u{d9}', ['\u{f9}', '\0', '\0']), ('\u{da}', ['\u{fa}', '\0', '\0']), ('\u{db}',
-        ['\u{fb}', '\0', '\0']), ('\u{dc}', ['\u{fc}', '\0', '\0']), ('\u{dd}', ['\u{fd}', '\0',
-        '\0']), ('\u{de}', ['\u{fe}', '\0', '\0']), ('\u{100}', ['\u{101}', '\0', '\0']),
-        ('\u{102}', ['\u{103}', '\0', '\0']), ('\u{104}', ['\u{105}', '\0', '\0']), ('\u{106}',
-        ['\u{107}', '\0', '\0']), ('\u{108}', ['\u{109}', '\0', '\0']), ('\u{10a}', ['\u{10b}',
-        '\0', '\0']), ('\u{10c}', ['\u{10d}', '\0', '\0']), ('\u{10e}', ['\u{10f}', '\0', '\0']),
-        ('\u{110}', ['\u{111}', '\0', '\0']), ('\u{112}', ['\u{113}', '\0', '\0']), ('\u{114}',
-        ['\u{115}', '\0', '\0']), ('\u{116}', ['\u{117}', '\0', '\0']), ('\u{118}', ['\u{119}',
-        '\0', '\0']), ('\u{11a}', ['\u{11b}', '\0', '\0']), ('\u{11c}', ['\u{11d}', '\0', '\0']),
-        ('\u{11e}', ['\u{11f}', '\0', '\0']), ('\u{120}', ['\u{121}', '\0', '\0']), ('\u{122}',
-        ['\u{123}', '\0', '\0']), ('\u{124}', ['\u{125}', '\0', '\0']), ('\u{126}', ['\u{127}',
-        '\0', '\0']), ('\u{128}', ['\u{129}', '\0', '\0']), ('\u{12a}', ['\u{12b}', '\0', '\0']),
-        ('\u{12c}', ['\u{12d}', '\0', '\0']), ('\u{12e}', ['\u{12f}', '\0', '\0']), ('\u{130}',
-        ['\u{69}', '\u{307}', '\0']), ('\u{132}', ['\u{133}', '\0', '\0']), ('\u{134}', ['\u{135}',
-        '\0', '\0']), ('\u{136}', ['\u{137}', '\0', '\0']), ('\u{139}', ['\u{13a}', '\0', '\0']),
-        ('\u{13b}', ['\u{13c}', '\0', '\0']), ('\u{13d}', ['\u{13e}', '\0', '\0']), ('\u{13f}',
-        ['\u{140}', '\0', '\0']), ('\u{141}', ['\u{142}', '\0', '\0']), ('\u{143}', ['\u{144}',
-        '\0', '\0']), ('\u{145}', ['\u{146}', '\0', '\0']), ('\u{147}', ['\u{148}', '\0', '\0']),
-        ('\u{14a}', ['\u{14b}', '\0', '\0']), ('\u{14c}', ['\u{14d}', '\0', '\0']), ('\u{14e}',
-        ['\u{14f}', '\0', '\0']), ('\u{150}', ['\u{151}', '\0', '\0']), ('\u{152}', ['\u{153}',
-        '\0', '\0']), ('\u{154}', ['\u{155}', '\0', '\0']), ('\u{156}', ['\u{157}', '\0', '\0']),
-        ('\u{158}', ['\u{159}', '\0', '\0']), ('\u{15a}', ['\u{15b}', '\0', '\0']), ('\u{15c}',
-        ['\u{15d}', '\0', '\0']), ('\u{15e}', ['\u{15f}', '\0', '\0']), ('\u{160}', ['\u{161}',
-        '\0', '\0']), ('\u{162}', ['\u{163}', '\0', '\0']), ('\u{164}', ['\u{165}', '\0', '\0']),
-        ('\u{166}', ['\u{167}', '\0', '\0']), ('\u{168}', ['\u{169}', '\0', '\0']), ('\u{16a}',
-        ['\u{16b}', '\0', '\0']), ('\u{16c}', ['\u{16d}', '\0', '\0']), ('\u{16e}', ['\u{16f}',
-        '\0', '\0']), ('\u{170}', ['\u{171}', '\0', '\0']), ('\u{172}', ['\u{173}', '\0', '\0']),
-        ('\u{174}', ['\u{175}', '\0', '\0']), ('\u{176}', ['\u{177}', '\0', '\0']), ('\u{178}',
-        ['\u{ff}', '\0', '\0']), ('\u{179}', ['\u{17a}', '\0', '\0']), ('\u{17b}', ['\u{17c}', '\0',
-        '\0']), ('\u{17d}', ['\u{17e}', '\0', '\0']), ('\u{181}', ['\u{253}', '\0', '\0']),
-        ('\u{182}', ['\u{183}', '\0', '\0']), ('\u{184}', ['\u{185}', '\0', '\0']), ('\u{186}',
-        ['\u{254}', '\0', '\0']), ('\u{187}', ['\u{188}', '\0', '\0']), ('\u{189}', ['\u{256}',
-        '\0', '\0']), ('\u{18a}', ['\u{257}', '\0', '\0']), ('\u{18b}', ['\u{18c}', '\0', '\0']),
-        ('\u{18e}', ['\u{1dd}', '\0', '\0']), ('\u{18f}', ['\u{259}', '\0', '\0']), ('\u{190}',
-        ['\u{25b}', '\0', '\0']), ('\u{191}', ['\u{192}', '\0', '\0']), ('\u{193}', ['\u{260}',
-        '\0', '\0']), ('\u{194}', ['\u{263}', '\0', '\0']), ('\u{196}', ['\u{269}', '\0', '\0']),
-        ('\u{197}', ['\u{268}', '\0', '\0']), ('\u{198}', ['\u{199}', '\0', '\0']), ('\u{19c}',
-        ['\u{26f}', '\0', '\0']), ('\u{19d}', ['\u{272}', '\0', '\0']), ('\u{19f}', ['\u{275}',
-        '\0', '\0']), ('\u{1a0}', ['\u{1a1}', '\0', '\0']), ('\u{1a2}', ['\u{1a3}', '\0', '\0']),
-        ('\u{1a4}', ['\u{1a5}', '\0', '\0']), ('\u{1a6}', ['\u{280}', '\0', '\0']), ('\u{1a7}',
-        ['\u{1a8}', '\0', '\0']), ('\u{1a9}', ['\u{283}', '\0', '\0']), ('\u{1ac}', ['\u{1ad}',
-        '\0', '\0']), ('\u{1ae}', ['\u{288}', '\0', '\0']), ('\u{1af}', ['\u{1b0}', '\0', '\0']),
-        ('\u{1b1}', ['\u{28a}', '\0', '\0']), ('\u{1b2}', ['\u{28b}', '\0', '\0']), ('\u{1b3}',
-        ['\u{1b4}', '\0', '\0']), ('\u{1b5}', ['\u{1b6}', '\0', '\0']), ('\u{1b7}', ['\u{292}',
-        '\0', '\0']), ('\u{1b8}', ['\u{1b9}', '\0', '\0']), ('\u{1bc}', ['\u{1bd}', '\0', '\0']),
-        ('\u{1c4}', ['\u{1c6}', '\0', '\0']), ('\u{1c5}', ['\u{1c6}', '\0', '\0']), ('\u{1c7}',
-        ['\u{1c9}', '\0', '\0']), ('\u{1c8}', ['\u{1c9}', '\0', '\0']), ('\u{1ca}', ['\u{1cc}',
-        '\0', '\0']), ('\u{1cb}', ['\u{1cc}', '\0', '\0']), ('\u{1cd}', ['\u{1ce}', '\0', '\0']),
-        ('\u{1cf}', ['\u{1d0}', '\0', '\0']), ('\u{1d1}', ['\u{1d2}', '\0', '\0']), ('\u{1d3}',
-        ['\u{1d4}', '\0', '\0']), ('\u{1d5}', ['\u{1d6}', '\0', '\0']), ('\u{1d7}', ['\u{1d8}',
-        '\0', '\0']), ('\u{1d9}', ['\u{1da}', '\0', '\0']), ('\u{1db}', ['\u{1dc}', '\0', '\0']),
-        ('\u{1de}', ['\u{1df}', '\0', '\0']), ('\u{1e0}', ['\u{1e1}', '\0', '\0']), ('\u{1e2}',
-        ['\u{1e3}', '\0', '\0']), ('\u{1e4}', ['\u{1e5}', '\0', '\0']), ('\u{1e6}', ['\u{1e7}',
-        '\0', '\0']), ('\u{1e8}', ['\u{1e9}', '\0', '\0']), ('\u{1ea}', ['\u{1eb}', '\0', '\0']),
-        ('\u{1ec}', ['\u{1ed}', '\0', '\0']), ('\u{1ee}', ['\u{1ef}', '\0', '\0']), ('\u{1f1}',
-        ['\u{1f3}', '\0', '\0']), ('\u{1f2}', ['\u{1f3}', '\0', '\0']), ('\u{1f4}', ['\u{1f5}',
-        '\0', '\0']), ('\u{1f6}', ['\u{195}', '\0', '\0']), ('\u{1f7}', ['\u{1bf}', '\0', '\0']),
-        ('\u{1f8}', ['\u{1f9}', '\0', '\0']), ('\u{1fa}', ['\u{1fb}', '\0', '\0']), ('\u{1fc}',
-        ['\u{1fd}', '\0', '\0']), ('\u{1fe}', ['\u{1ff}', '\0', '\0']), ('\u{200}', ['\u{201}',
-        '\0', '\0']), ('\u{202}', ['\u{203}', '\0', '\0']), ('\u{204}', ['\u{205}', '\0', '\0']),
-        ('\u{206}', ['\u{207}', '\0', '\0']), ('\u{208}', ['\u{209}', '\0', '\0']), ('\u{20a}',
-        ['\u{20b}', '\0', '\0']), ('\u{20c}', ['\u{20d}', '\0', '\0']), ('\u{20e}', ['\u{20f}',
-        '\0', '\0']), ('\u{210}', ['\u{211}', '\0', '\0']), ('\u{212}', ['\u{213}', '\0', '\0']),
-        ('\u{214}', ['\u{215}', '\0', '\0']), ('\u{216}', ['\u{217}', '\0', '\0']), ('\u{218}',
-        ['\u{219}', '\0', '\0']), ('\u{21a}', ['\u{21b}', '\0', '\0']), ('\u{21c}', ['\u{21d}',
-        '\0', '\0']), ('\u{21e}', ['\u{21f}', '\0', '\0']), ('\u{220}', ['\u{19e}', '\0', '\0']),
-        ('\u{222}', ['\u{223}', '\0', '\0']), ('\u{224}', ['\u{225}', '\0', '\0']), ('\u{226}',
-        ['\u{227}', '\0', '\0']), ('\u{228}', ['\u{229}', '\0', '\0']), ('\u{22a}', ['\u{22b}',
-        '\0', '\0']), ('\u{22c}', ['\u{22d}', '\0', '\0']), ('\u{22e}', ['\u{22f}', '\0', '\0']),
-        ('\u{230}', ['\u{231}', '\0', '\0']), ('\u{232}', ['\u{233}', '\0', '\0']), ('\u{23a}',
-        ['\u{2c65}', '\0', '\0']), ('\u{23b}', ['\u{23c}', '\0', '\0']), ('\u{23d}', ['\u{19a}',
-        '\0', '\0']), ('\u{23e}', ['\u{2c66}', '\0', '\0']), ('\u{241}', ['\u{242}', '\0', '\0']),
-        ('\u{243}', ['\u{180}', '\0', '\0']), ('\u{244}', ['\u{289}', '\0', '\0']), ('\u{245}',
-        ['\u{28c}', '\0', '\0']), ('\u{246}', ['\u{247}', '\0', '\0']), ('\u{248}', ['\u{249}',
-        '\0', '\0']), ('\u{24a}', ['\u{24b}', '\0', '\0']), ('\u{24c}', ['\u{24d}', '\0', '\0']),
-        ('\u{24e}', ['\u{24f}', '\0', '\0']), ('\u{370}', ['\u{371}', '\0', '\0']), ('\u{372}',
-        ['\u{373}', '\0', '\0']), ('\u{376}', ['\u{377}', '\0', '\0']), ('\u{37f}', ['\u{3f3}',
-        '\0', '\0']), ('\u{386}', ['\u{3ac}', '\0', '\0']), ('\u{388}', ['\u{3ad}', '\0', '\0']),
-        ('\u{389}', ['\u{3ae}', '\0', '\0']), ('\u{38a}', ['\u{3af}', '\0', '\0']), ('\u{38c}',
-        ['\u{3cc}', '\0', '\0']), ('\u{38e}', ['\u{3cd}', '\0', '\0']), ('\u{38f}', ['\u{3ce}',
-        '\0', '\0']), ('\u{391}', ['\u{3b1}', '\0', '\0']), ('\u{392}', ['\u{3b2}', '\0', '\0']),
-        ('\u{393}', ['\u{3b3}', '\0', '\0']), ('\u{394}', ['\u{3b4}', '\0', '\0']), ('\u{395}',
-        ['\u{3b5}', '\0', '\0']), ('\u{396}', ['\u{3b6}', '\0', '\0']), ('\u{397}', ['\u{3b7}',
-        '\0', '\0']), ('\u{398}', ['\u{3b8}', '\0', '\0']), ('\u{399}', ['\u{3b9}', '\0', '\0']),
-        ('\u{39a}', ['\u{3ba}', '\0', '\0']), ('\u{39b}', ['\u{3bb}', '\0', '\0']), ('\u{39c}',
-        ['\u{3bc}', '\0', '\0']), ('\u{39d}', ['\u{3bd}', '\0', '\0']), ('\u{39e}', ['\u{3be}',
-        '\0', '\0']), ('\u{39f}', ['\u{3bf}', '\0', '\0']), ('\u{3a0}', ['\u{3c0}', '\0', '\0']),
-        ('\u{3a1}', ['\u{3c1}', '\0', '\0']), ('\u{3a3}', ['\u{3c3}', '\0', '\0']), ('\u{3a4}',
-        ['\u{3c4}', '\0', '\0']), ('\u{3a5}', ['\u{3c5}', '\0', '\0']), ('\u{3a6}', ['\u{3c6}',
-        '\0', '\0']), ('\u{3a7}', ['\u{3c7}', '\0', '\0']), ('\u{3a8}', ['\u{3c8}', '\0', '\0']),
-        ('\u{3a9}', ['\u{3c9}', '\0', '\0']), ('\u{3aa}', ['\u{3ca}', '\0', '\0']), ('\u{3ab}',
-        ['\u{3cb}', '\0', '\0']), ('\u{3cf}', ['\u{3d7}', '\0', '\0']), ('\u{3d8}', ['\u{3d9}',
-        '\0', '\0']), ('\u{3da}', ['\u{3db}', '\0', '\0']), ('\u{3dc}', ['\u{3dd}', '\0', '\0']),
-        ('\u{3de}', ['\u{3df}', '\0', '\0']), ('\u{3e0}', ['\u{3e1}', '\0', '\0']), ('\u{3e2}',
-        ['\u{3e3}', '\0', '\0']), ('\u{3e4}', ['\u{3e5}', '\0', '\0']), ('\u{3e6}', ['\u{3e7}',
-        '\0', '\0']), ('\u{3e8}', ['\u{3e9}', '\0', '\0']), ('\u{3ea}', ['\u{3eb}', '\0', '\0']),
-        ('\u{3ec}', ['\u{3ed}', '\0', '\0']), ('\u{3ee}', ['\u{3ef}', '\0', '\0']), ('\u{3f4}',
-        ['\u{3b8}', '\0', '\0']), ('\u{3f7}', ['\u{3f8}', '\0', '\0']), ('\u{3f9}', ['\u{3f2}',
-        '\0', '\0']), ('\u{3fa}', ['\u{3fb}', '\0', '\0']), ('\u{3fd}', ['\u{37b}', '\0', '\0']),
-        ('\u{3fe}', ['\u{37c}', '\0', '\0']), ('\u{3ff}', ['\u{37d}', '\0', '\0']), ('\u{400}',
-        ['\u{450}', '\0', '\0']), ('\u{401}', ['\u{451}', '\0', '\0']), ('\u{402}', ['\u{452}',
-        '\0', '\0']), ('\u{403}', ['\u{453}', '\0', '\0']), ('\u{404}', ['\u{454}', '\0', '\0']),
-        ('\u{405}', ['\u{455}', '\0', '\0']), ('\u{406}', ['\u{456}', '\0', '\0']), ('\u{407}',
-        ['\u{457}', '\0', '\0']), ('\u{408}', ['\u{458}', '\0', '\0']), ('\u{409}', ['\u{459}',
-        '\0', '\0']), ('\u{40a}', ['\u{45a}', '\0', '\0']), ('\u{40b}', ['\u{45b}', '\0', '\0']),
-        ('\u{40c}', ['\u{45c}', '\0', '\0']), ('\u{40d}', ['\u{45d}', '\0', '\0']), ('\u{40e}',
-        ['\u{45e}', '\0', '\0']), ('\u{40f}', ['\u{45f}', '\0', '\0']), ('\u{410}', ['\u{430}',
-        '\0', '\0']), ('\u{411}', ['\u{431}', '\0', '\0']), ('\u{412}', ['\u{432}', '\0', '\0']),
-        ('\u{413}', ['\u{433}', '\0', '\0']), ('\u{414}', ['\u{434}', '\0', '\0']), ('\u{415}',
-        ['\u{435}', '\0', '\0']), ('\u{416}', ['\u{436}', '\0', '\0']), ('\u{417}', ['\u{437}',
-        '\0', '\0']), ('\u{418}', ['\u{438}', '\0', '\0']), ('\u{419}', ['\u{439}', '\0', '\0']),
-        ('\u{41a}', ['\u{43a}', '\0', '\0']), ('\u{41b}', ['\u{43b}', '\0', '\0']), ('\u{41c}',
-        ['\u{43c}', '\0', '\0']), ('\u{41d}', ['\u{43d}', '\0', '\0']), ('\u{41e}', ['\u{43e}',
-        '\0', '\0']), ('\u{41f}', ['\u{43f}', '\0', '\0']), ('\u{420}', ['\u{440}', '\0', '\0']),
-        ('\u{421}', ['\u{441}', '\0', '\0']), ('\u{422}', ['\u{442}', '\0', '\0']), ('\u{423}',
-        ['\u{443}', '\0', '\0']), ('\u{424}', ['\u{444}', '\0', '\0']), ('\u{425}', ['\u{445}',
-        '\0', '\0']), ('\u{426}', ['\u{446}', '\0', '\0']), ('\u{427}', ['\u{447}', '\0', '\0']),
-        ('\u{428}', ['\u{448}', '\0', '\0']), ('\u{429}', ['\u{449}', '\0', '\0']), ('\u{42a}',
-        ['\u{44a}', '\0', '\0']), ('\u{42b}', ['\u{44b}', '\0', '\0']), ('\u{42c}', ['\u{44c}',
-        '\0', '\0']), ('\u{42d}', ['\u{44d}', '\0', '\0']), ('\u{42e}', ['\u{44e}', '\0', '\0']),
-        ('\u{42f}', ['\u{44f}', '\0', '\0']), ('\u{460}', ['\u{461}', '\0', '\0']), ('\u{462}',
-        ['\u{463}', '\0', '\0']), ('\u{464}', ['\u{465}', '\0', '\0']), ('\u{466}', ['\u{467}',
-        '\0', '\0']), ('\u{468}', ['\u{469}', '\0', '\0']), ('\u{46a}', ['\u{46b}', '\0', '\0']),
-        ('\u{46c}', ['\u{46d}', '\0', '\0']), ('\u{46e}', ['\u{46f}', '\0', '\0']), ('\u{470}',
-        ['\u{471}', '\0', '\0']), ('\u{472}', ['\u{473}', '\0', '\0']), ('\u{474}', ['\u{475}',
-        '\0', '\0']), ('\u{476}', ['\u{477}', '\0', '\0']), ('\u{478}', ['\u{479}', '\0', '\0']),
-        ('\u{47a}', ['\u{47b}', '\0', '\0']), ('\u{47c}', ['\u{47d}', '\0', '\0']), ('\u{47e}',
-        ['\u{47f}', '\0', '\0']), ('\u{480}', ['\u{481}', '\0', '\0']), ('\u{48a}', ['\u{48b}',
-        '\0', '\0']), ('\u{48c}', ['\u{48d}', '\0', '\0']), ('\u{48e}', ['\u{48f}', '\0', '\0']),
-        ('\u{490}', ['\u{491}', '\0', '\0']), ('\u{492}', ['\u{493}', '\0', '\0']), ('\u{494}',
-        ['\u{495}', '\0', '\0']), ('\u{496}', ['\u{497}', '\0', '\0']), ('\u{498}', ['\u{499}',
-        '\0', '\0']), ('\u{49a}', ['\u{49b}', '\0', '\0']), ('\u{49c}', ['\u{49d}', '\0', '\0']),
-        ('\u{49e}', ['\u{49f}', '\0', '\0']), ('\u{4a0}', ['\u{4a1}', '\0', '\0']), ('\u{4a2}',
-        ['\u{4a3}', '\0', '\0']), ('\u{4a4}', ['\u{4a5}', '\0', '\0']), ('\u{4a6}', ['\u{4a7}',
-        '\0', '\0']), ('\u{4a8}', ['\u{4a9}', '\0', '\0']), ('\u{4aa}', ['\u{4ab}', '\0', '\0']),
-        ('\u{4ac}', ['\u{4ad}', '\0', '\0']), ('\u{4ae}', ['\u{4af}', '\0', '\0']), ('\u{4b0}',
-        ['\u{4b1}', '\0', '\0']), ('\u{4b2}', ['\u{4b3}', '\0', '\0']), ('\u{4b4}', ['\u{4b5}',
-        '\0', '\0']), ('\u{4b6}', ['\u{4b7}', '\0', '\0']), ('\u{4b8}', ['\u{4b9}', '\0', '\0']),
-        ('\u{4ba}', ['\u{4bb}', '\0', '\0']), ('\u{4bc}', ['\u{4bd}', '\0', '\0']), ('\u{4be}',
-        ['\u{4bf}', '\0', '\0']), ('\u{4c0}', ['\u{4cf}', '\0', '\0']), ('\u{4c1}', ['\u{4c2}',
-        '\0', '\0']), ('\u{4c3}', ['\u{4c4}', '\0', '\0']), ('\u{4c5}', ['\u{4c6}', '\0', '\0']),
-        ('\u{4c7}', ['\u{4c8}', '\0', '\0']), ('\u{4c9}', ['\u{4ca}', '\0', '\0']), ('\u{4cb}',
-        ['\u{4cc}', '\0', '\0']), ('\u{4cd}', ['\u{4ce}', '\0', '\0']), ('\u{4d0}', ['\u{4d1}',
-        '\0', '\0']), ('\u{4d2}', ['\u{4d3}', '\0', '\0']), ('\u{4d4}', ['\u{4d5}', '\0', '\0']),
-        ('\u{4d6}', ['\u{4d7}', '\0', '\0']), ('\u{4d8}', ['\u{4d9}', '\0', '\0']), ('\u{4da}',
-        ['\u{4db}', '\0', '\0']), ('\u{4dc}', ['\u{4dd}', '\0', '\0']), ('\u{4de}', ['\u{4df}',
-        '\0', '\0']), ('\u{4e0}', ['\u{4e1}', '\0', '\0']), ('\u{4e2}', ['\u{4e3}', '\0', '\0']),
-        ('\u{4e4}', ['\u{4e5}', '\0', '\0']), ('\u{4e6}', ['\u{4e7}', '\0', '\0']), ('\u{4e8}',
-        ['\u{4e9}', '\0', '\0']), ('\u{4ea}', ['\u{4eb}', '\0', '\0']), ('\u{4ec}', ['\u{4ed}',
-        '\0', '\0']), ('\u{4ee}', ['\u{4ef}', '\0', '\0']), ('\u{4f0}', ['\u{4f1}', '\0', '\0']),
-        ('\u{4f2}', ['\u{4f3}', '\0', '\0']), ('\u{4f4}', ['\u{4f5}', '\0', '\0']), ('\u{4f6}',
-        ['\u{4f7}', '\0', '\0']), ('\u{4f8}', ['\u{4f9}', '\0', '\0']), ('\u{4fa}', ['\u{4fb}',
-        '\0', '\0']), ('\u{4fc}', ['\u{4fd}', '\0', '\0']), ('\u{4fe}', ['\u{4ff}', '\0', '\0']),
-        ('\u{500}', ['\u{501}', '\0', '\0']), ('\u{502}', ['\u{503}', '\0', '\0']), ('\u{504}',
-        ['\u{505}', '\0', '\0']), ('\u{506}', ['\u{507}', '\0', '\0']), ('\u{508}', ['\u{509}',
-        '\0', '\0']), ('\u{50a}', ['\u{50b}', '\0', '\0']), ('\u{50c}', ['\u{50d}', '\0', '\0']),
-        ('\u{50e}', ['\u{50f}', '\0', '\0']), ('\u{510}', ['\u{511}', '\0', '\0']), ('\u{512}',
-        ['\u{513}', '\0', '\0']), ('\u{514}', ['\u{515}', '\0', '\0']), ('\u{516}', ['\u{517}',
-        '\0', '\0']), ('\u{518}', ['\u{519}', '\0', '\0']), ('\u{51a}', ['\u{51b}', '\0', '\0']),
-        ('\u{51c}', ['\u{51d}', '\0', '\0']), ('\u{51e}', ['\u{51f}', '\0', '\0']), ('\u{520}',
-        ['\u{521}', '\0', '\0']), ('\u{522}', ['\u{523}', '\0', '\0']), ('\u{524}', ['\u{525}',
-        '\0', '\0']), ('\u{526}', ['\u{527}', '\0', '\0']), ('\u{528}', ['\u{529}', '\0', '\0']),
-        ('\u{52a}', ['\u{52b}', '\0', '\0']), ('\u{52c}', ['\u{52d}', '\0', '\0']), ('\u{52e}',
-        ['\u{52f}', '\0', '\0']), ('\u{531}', ['\u{561}', '\0', '\0']), ('\u{532}', ['\u{562}',
-        '\0', '\0']), ('\u{533}', ['\u{563}', '\0', '\0']), ('\u{534}', ['\u{564}', '\0', '\0']),
-        ('\u{535}', ['\u{565}', '\0', '\0']), ('\u{536}', ['\u{566}', '\0', '\0']), ('\u{537}',
-        ['\u{567}', '\0', '\0']), ('\u{538}', ['\u{568}', '\0', '\0']), ('\u{539}', ['\u{569}',
-        '\0', '\0']), ('\u{53a}', ['\u{56a}', '\0', '\0']), ('\u{53b}', ['\u{56b}', '\0', '\0']),
-        ('\u{53c}', ['\u{56c}', '\0', '\0']), ('\u{53d}', ['\u{56d}', '\0', '\0']), ('\u{53e}',
-        ['\u{56e}', '\0', '\0']), ('\u{53f}', ['\u{56f}', '\0', '\0']), ('\u{540}', ['\u{570}',
-        '\0', '\0']), ('\u{541}', ['\u{571}', '\0', '\0']), ('\u{542}', ['\u{572}', '\0', '\0']),
-        ('\u{543}', ['\u{573}', '\0', '\0']), ('\u{544}', ['\u{574}', '\0', '\0']), ('\u{545}',
-        ['\u{575}', '\0', '\0']), ('\u{546}', ['\u{576}', '\0', '\0']), ('\u{547}', ['\u{577}',
-        '\0', '\0']), ('\u{548}', ['\u{578}', '\0', '\0']), ('\u{549}', ['\u{579}', '\0', '\0']),
-        ('\u{54a}', ['\u{57a}', '\0', '\0']), ('\u{54b}', ['\u{57b}', '\0', '\0']), ('\u{54c}',
-        ['\u{57c}', '\0', '\0']), ('\u{54d}', ['\u{57d}', '\0', '\0']), ('\u{54e}', ['\u{57e}',
-        '\0', '\0']), ('\u{54f}', ['\u{57f}', '\0', '\0']), ('\u{550}', ['\u{580}', '\0', '\0']),
-        ('\u{551}', ['\u{581}', '\0', '\0']), ('\u{552}', ['\u{582}', '\0', '\0']), ('\u{553}',
-        ['\u{583}', '\0', '\0']), ('\u{554}', ['\u{584}', '\0', '\0']), ('\u{555}', ['\u{585}',
-        '\0', '\0']), ('\u{556}', ['\u{586}', '\0', '\0']), ('\u{10a0}', ['\u{2d00}', '\0', '\0']),
-        ('\u{10a1}', ['\u{2d01}', '\0', '\0']), ('\u{10a2}', ['\u{2d02}', '\0', '\0']), ('\u{10a3}',
-        ['\u{2d03}', '\0', '\0']), ('\u{10a4}', ['\u{2d04}', '\0', '\0']), ('\u{10a5}', ['\u{2d05}',
-        '\0', '\0']), ('\u{10a6}', ['\u{2d06}', '\0', '\0']), ('\u{10a7}', ['\u{2d07}', '\0',
-        '\0']), ('\u{10a8}', ['\u{2d08}', '\0', '\0']), ('\u{10a9}', ['\u{2d09}', '\0', '\0']),
-        ('\u{10aa}', ['\u{2d0a}', '\0', '\0']), ('\u{10ab}', ['\u{2d0b}', '\0', '\0']), ('\u{10ac}',
-        ['\u{2d0c}', '\0', '\0']), ('\u{10ad}', ['\u{2d0d}', '\0', '\0']), ('\u{10ae}', ['\u{2d0e}',
-        '\0', '\0']), ('\u{10af}', ['\u{2d0f}', '\0', '\0']), ('\u{10b0}', ['\u{2d10}', '\0',
-        '\0']), ('\u{10b1}', ['\u{2d11}', '\0', '\0']), ('\u{10b2}', ['\u{2d12}', '\0', '\0']),
-        ('\u{10b3}', ['\u{2d13}', '\0', '\0']), ('\u{10b4}', ['\u{2d14}', '\0', '\0']), ('\u{10b5}',
-        ['\u{2d15}', '\0', '\0']), ('\u{10b6}', ['\u{2d16}', '\0', '\0']), ('\u{10b7}', ['\u{2d17}',
-        '\0', '\0']), ('\u{10b8}', ['\u{2d18}', '\0', '\0']), ('\u{10b9}', ['\u{2d19}', '\0',
-        '\0']), ('\u{10ba}', ['\u{2d1a}', '\0', '\0']), ('\u{10bb}', ['\u{2d1b}', '\0', '\0']),
-        ('\u{10bc}', ['\u{2d1c}', '\0', '\0']), ('\u{10bd}', ['\u{2d1d}', '\0', '\0']), ('\u{10be}',
-        ['\u{2d1e}', '\0', '\0']), ('\u{10bf}', ['\u{2d1f}', '\0', '\0']), ('\u{10c0}', ['\u{2d20}',
-        '\0', '\0']), ('\u{10c1}', ['\u{2d21}', '\0', '\0']), ('\u{10c2}', ['\u{2d22}', '\0',
-        '\0']), ('\u{10c3}', ['\u{2d23}', '\0', '\0']), ('\u{10c4}', ['\u{2d24}', '\0', '\0']),
-        ('\u{10c5}', ['\u{2d25}', '\0', '\0']), ('\u{10c7}', ['\u{2d27}', '\0', '\0']), ('\u{10cd}',
-        ['\u{2d2d}', '\0', '\0']), ('\u{13a0}', ['\u{ab70}', '\0', '\0']), ('\u{13a1}', ['\u{ab71}',
-        '\0', '\0']), ('\u{13a2}', ['\u{ab72}', '\0', '\0']), ('\u{13a3}', ['\u{ab73}', '\0',
-        '\0']), ('\u{13a4}', ['\u{ab74}', '\0', '\0']), ('\u{13a5}', ['\u{ab75}', '\0', '\0']),
-        ('\u{13a6}', ['\u{ab76}', '\0', '\0']), ('\u{13a7}', ['\u{ab77}', '\0', '\0']), ('\u{13a8}',
-        ['\u{ab78}', '\0', '\0']), ('\u{13a9}', ['\u{ab79}', '\0', '\0']), ('\u{13aa}', ['\u{ab7a}',
-        '\0', '\0']), ('\u{13ab}', ['\u{ab7b}', '\0', '\0']), ('\u{13ac}', ['\u{ab7c}', '\0',
-        '\0']), ('\u{13ad}', ['\u{ab7d}', '\0', '\0']), ('\u{13ae}', ['\u{ab7e}', '\0', '\0']),
-        ('\u{13af}', ['\u{ab7f}', '\0', '\0']), ('\u{13b0}', ['\u{ab80}', '\0', '\0']), ('\u{13b1}',
-        ['\u{ab81}', '\0', '\0']), ('\u{13b2}', ['\u{ab82}', '\0', '\0']), ('\u{13b3}', ['\u{ab83}',
-        '\0', '\0']), ('\u{13b4}', ['\u{ab84}', '\0', '\0']), ('\u{13b5}', ['\u{ab85}', '\0',
-        '\0']), ('\u{13b6}', ['\u{ab86}', '\0', '\0']), ('\u{13b7}', ['\u{ab87}', '\0', '\0']),
-        ('\u{13b8}', ['\u{ab88}', '\0', '\0']), ('\u{13b9}', ['\u{ab89}', '\0', '\0']), ('\u{13ba}',
-        ['\u{ab8a}', '\0', '\0']), ('\u{13bb}', ['\u{ab8b}', '\0', '\0']), ('\u{13bc}', ['\u{ab8c}',
-        '\0', '\0']), ('\u{13bd}', ['\u{ab8d}', '\0', '\0']), ('\u{13be}', ['\u{ab8e}', '\0',
-        '\0']), ('\u{13bf}', ['\u{ab8f}', '\0', '\0']), ('\u{13c0}', ['\u{ab90}', '\0', '\0']),
-        ('\u{13c1}', ['\u{ab91}', '\0', '\0']), ('\u{13c2}', ['\u{ab92}', '\0', '\0']), ('\u{13c3}',
-        ['\u{ab93}', '\0', '\0']), ('\u{13c4}', ['\u{ab94}', '\0', '\0']), ('\u{13c5}', ['\u{ab95}',
-        '\0', '\0']), ('\u{13c6}', ['\u{ab96}', '\0', '\0']), ('\u{13c7}', ['\u{ab97}', '\0',
-        '\0']), ('\u{13c8}', ['\u{ab98}', '\0', '\0']), ('\u{13c9}', ['\u{ab99}', '\0', '\0']),
-        ('\u{13ca}', ['\u{ab9a}', '\0', '\0']), ('\u{13cb}', ['\u{ab9b}', '\0', '\0']), ('\u{13cc}',
-        ['\u{ab9c}', '\0', '\0']), ('\u{13cd}', ['\u{ab9d}', '\0', '\0']), ('\u{13ce}', ['\u{ab9e}',
-        '\0', '\0']), ('\u{13cf}', ['\u{ab9f}', '\0', '\0']), ('\u{13d0}', ['\u{aba0}', '\0',
-        '\0']), ('\u{13d1}', ['\u{aba1}', '\0', '\0']), ('\u{13d2}', ['\u{aba2}', '\0', '\0']),
-        ('\u{13d3}', ['\u{aba3}', '\0', '\0']), ('\u{13d4}', ['\u{aba4}', '\0', '\0']), ('\u{13d5}',
-        ['\u{aba5}', '\0', '\0']), ('\u{13d6}', ['\u{aba6}', '\0', '\0']), ('\u{13d7}', ['\u{aba7}',
-        '\0', '\0']), ('\u{13d8}', ['\u{aba8}', '\0', '\0']), ('\u{13d9}', ['\u{aba9}', '\0',
-        '\0']), ('\u{13da}', ['\u{abaa}', '\0', '\0']), ('\u{13db}', ['\u{abab}', '\0', '\0']),
-        ('\u{13dc}', ['\u{abac}', '\0', '\0']), ('\u{13dd}', ['\u{abad}', '\0', '\0']), ('\u{13de}',
-        ['\u{abae}', '\0', '\0']), ('\u{13df}', ['\u{abaf}', '\0', '\0']), ('\u{13e0}', ['\u{abb0}',
-        '\0', '\0']), ('\u{13e1}', ['\u{abb1}', '\0', '\0']), ('\u{13e2}', ['\u{abb2}', '\0',
-        '\0']), ('\u{13e3}', ['\u{abb3}', '\0', '\0']), ('\u{13e4}', ['\u{abb4}', '\0', '\0']),
-        ('\u{13e5}', ['\u{abb5}', '\0', '\0']), ('\u{13e6}', ['\u{abb6}', '\0', '\0']), ('\u{13e7}',
-        ['\u{abb7}', '\0', '\0']), ('\u{13e8}', ['\u{abb8}', '\0', '\0']), ('\u{13e9}', ['\u{abb9}',
-        '\0', '\0']), ('\u{13ea}', ['\u{abba}', '\0', '\0']), ('\u{13eb}', ['\u{abbb}', '\0',
-        '\0']), ('\u{13ec}', ['\u{abbc}', '\0', '\0']), ('\u{13ed}', ['\u{abbd}', '\0', '\0']),
-        ('\u{13ee}', ['\u{abbe}', '\0', '\0']), ('\u{13ef}', ['\u{abbf}', '\0', '\0']), ('\u{13f0}',
-        ['\u{13f8}', '\0', '\0']), ('\u{13f1}', ['\u{13f9}', '\0', '\0']), ('\u{13f2}', ['\u{13fa}',
-        '\0', '\0']), ('\u{13f3}', ['\u{13fb}', '\0', '\0']), ('\u{13f4}', ['\u{13fc}', '\0',
-        '\0']), ('\u{13f5}', ['\u{13fd}', '\0', '\0']), ('\u{1c90}', ['\u{10d0}', '\0', '\0']),
-        ('\u{1c91}', ['\u{10d1}', '\0', '\0']), ('\u{1c92}', ['\u{10d2}', '\0', '\0']), ('\u{1c93}',
-        ['\u{10d3}', '\0', '\0']), ('\u{1c94}', ['\u{10d4}', '\0', '\0']), ('\u{1c95}', ['\u{10d5}',
-        '\0', '\0']), ('\u{1c96}', ['\u{10d6}', '\0', '\0']), ('\u{1c97}', ['\u{10d7}', '\0',
-        '\0']), ('\u{1c98}', ['\u{10d8}', '\0', '\0']), ('\u{1c99}', ['\u{10d9}', '\0', '\0']),
-        ('\u{1c9a}', ['\u{10da}', '\0', '\0']), ('\u{1c9b}', ['\u{10db}', '\0', '\0']), ('\u{1c9c}',
-        ['\u{10dc}', '\0', '\0']), ('\u{1c9d}', ['\u{10dd}', '\0', '\0']), ('\u{1c9e}', ['\u{10de}',
-        '\0', '\0']), ('\u{1c9f}', ['\u{10df}', '\0', '\0']), ('\u{1ca0}', ['\u{10e0}', '\0',
-        '\0']), ('\u{1ca1}', ['\u{10e1}', '\0', '\0']), ('\u{1ca2}', ['\u{10e2}', '\0', '\0']),
-        ('\u{1ca3}', ['\u{10e3}', '\0', '\0']), ('\u{1ca4}', ['\u{10e4}', '\0', '\0']), ('\u{1ca5}',
-        ['\u{10e5}', '\0', '\0']), ('\u{1ca6}', ['\u{10e6}', '\0', '\0']), ('\u{1ca7}', ['\u{10e7}',
-        '\0', '\0']), ('\u{1ca8}', ['\u{10e8}', '\0', '\0']), ('\u{1ca9}', ['\u{10e9}', '\0',
-        '\0']), ('\u{1caa}', ['\u{10ea}', '\0', '\0']), ('\u{1cab}', ['\u{10eb}', '\0', '\0']),
-        ('\u{1cac}', ['\u{10ec}', '\0', '\0']), ('\u{1cad}', ['\u{10ed}', '\0', '\0']), ('\u{1cae}',
-        ['\u{10ee}', '\0', '\0']), ('\u{1caf}', ['\u{10ef}', '\0', '\0']), ('\u{1cb0}', ['\u{10f0}',
-        '\0', '\0']), ('\u{1cb1}', ['\u{10f1}', '\0', '\0']), ('\u{1cb2}', ['\u{10f2}', '\0',
-        '\0']), ('\u{1cb3}', ['\u{10f3}', '\0', '\0']), ('\u{1cb4}', ['\u{10f4}', '\0', '\0']),
-        ('\u{1cb5}', ['\u{10f5}', '\0', '\0']), ('\u{1cb6}', ['\u{10f6}', '\0', '\0']), ('\u{1cb7}',
-        ['\u{10f7}', '\0', '\0']), ('\u{1cb8}', ['\u{10f8}', '\0', '\0']), ('\u{1cb9}', ['\u{10f9}',
-        '\0', '\0']), ('\u{1cba}', ['\u{10fa}', '\0', '\0']), ('\u{1cbd}', ['\u{10fd}', '\0',
-        '\0']), ('\u{1cbe}', ['\u{10fe}', '\0', '\0']), ('\u{1cbf}', ['\u{10ff}', '\0', '\0']),
-        ('\u{1e00}', ['\u{1e01}', '\0', '\0']), ('\u{1e02}', ['\u{1e03}', '\0', '\0']), ('\u{1e04}',
-        ['\u{1e05}', '\0', '\0']), ('\u{1e06}', ['\u{1e07}', '\0', '\0']), ('\u{1e08}', ['\u{1e09}',
-        '\0', '\0']), ('\u{1e0a}', ['\u{1e0b}', '\0', '\0']), ('\u{1e0c}', ['\u{1e0d}', '\0',
-        '\0']), ('\u{1e0e}', ['\u{1e0f}', '\0', '\0']), ('\u{1e10}', ['\u{1e11}', '\0', '\0']),
-        ('\u{1e12}', ['\u{1e13}', '\0', '\0']), ('\u{1e14}', ['\u{1e15}', '\0', '\0']), ('\u{1e16}',
-        ['\u{1e17}', '\0', '\0']), ('\u{1e18}', ['\u{1e19}', '\0', '\0']), ('\u{1e1a}', ['\u{1e1b}',
-        '\0', '\0']), ('\u{1e1c}', ['\u{1e1d}', '\0', '\0']), ('\u{1e1e}', ['\u{1e1f}', '\0',
-        '\0']), ('\u{1e20}', ['\u{1e21}', '\0', '\0']), ('\u{1e22}', ['\u{1e23}', '\0', '\0']),
-        ('\u{1e24}', ['\u{1e25}', '\0', '\0']), ('\u{1e26}', ['\u{1e27}', '\0', '\0']), ('\u{1e28}',
-        ['\u{1e29}', '\0', '\0']), ('\u{1e2a}', ['\u{1e2b}', '\0', '\0']), ('\u{1e2c}', ['\u{1e2d}',
-        '\0', '\0']), ('\u{1e2e}', ['\u{1e2f}', '\0', '\0']), ('\u{1e30}', ['\u{1e31}', '\0',
-        '\0']), ('\u{1e32}', ['\u{1e33}', '\0', '\0']), ('\u{1e34}', ['\u{1e35}', '\0', '\0']),
-        ('\u{1e36}', ['\u{1e37}', '\0', '\0']), ('\u{1e38}', ['\u{1e39}', '\0', '\0']), ('\u{1e3a}',
-        ['\u{1e3b}', '\0', '\0']), ('\u{1e3c}', ['\u{1e3d}', '\0', '\0']), ('\u{1e3e}', ['\u{1e3f}',
-        '\0', '\0']), ('\u{1e40}', ['\u{1e41}', '\0', '\0']), ('\u{1e42}', ['\u{1e43}', '\0',
-        '\0']), ('\u{1e44}', ['\u{1e45}', '\0', '\0']), ('\u{1e46}', ['\u{1e47}', '\0', '\0']),
-        ('\u{1e48}', ['\u{1e49}', '\0', '\0']), ('\u{1e4a}', ['\u{1e4b}', '\0', '\0']), ('\u{1e4c}',
-        ['\u{1e4d}', '\0', '\0']), ('\u{1e4e}', ['\u{1e4f}', '\0', '\0']), ('\u{1e50}', ['\u{1e51}',
-        '\0', '\0']), ('\u{1e52}', ['\u{1e53}', '\0', '\0']), ('\u{1e54}', ['\u{1e55}', '\0',
-        '\0']), ('\u{1e56}', ['\u{1e57}', '\0', '\0']), ('\u{1e58}', ['\u{1e59}', '\0', '\0']),
-        ('\u{1e5a}', ['\u{1e5b}', '\0', '\0']), ('\u{1e5c}', ['\u{1e5d}', '\0', '\0']), ('\u{1e5e}',
-        ['\u{1e5f}', '\0', '\0']), ('\u{1e60}', ['\u{1e61}', '\0', '\0']), ('\u{1e62}', ['\u{1e63}',
-        '\0', '\0']), ('\u{1e64}', ['\u{1e65}', '\0', '\0']), ('\u{1e66}', ['\u{1e67}', '\0',
-        '\0']), ('\u{1e68}', ['\u{1e69}', '\0', '\0']), ('\u{1e6a}', ['\u{1e6b}', '\0', '\0']),
-        ('\u{1e6c}', ['\u{1e6d}', '\0', '\0']), ('\u{1e6e}', ['\u{1e6f}', '\0', '\0']), ('\u{1e70}',
-        ['\u{1e71}', '\0', '\0']), ('\u{1e72}', ['\u{1e73}', '\0', '\0']), ('\u{1e74}', ['\u{1e75}',
-        '\0', '\0']), ('\u{1e76}', ['\u{1e77}', '\0', '\0']), ('\u{1e78}', ['\u{1e79}', '\0',
-        '\0']), ('\u{1e7a}', ['\u{1e7b}', '\0', '\0']), ('\u{1e7c}', ['\u{1e7d}', '\0', '\0']),
-        ('\u{1e7e}', ['\u{1e7f}', '\0', '\0']), ('\u{1e80}', ['\u{1e81}', '\0', '\0']), ('\u{1e82}',
-        ['\u{1e83}', '\0', '\0']), ('\u{1e84}', ['\u{1e85}', '\0', '\0']), ('\u{1e86}', ['\u{1e87}',
-        '\0', '\0']), ('\u{1e88}', ['\u{1e89}', '\0', '\0']), ('\u{1e8a}', ['\u{1e8b}', '\0',
-        '\0']), ('\u{1e8c}', ['\u{1e8d}', '\0', '\0']), ('\u{1e8e}', ['\u{1e8f}', '\0', '\0']),
-        ('\u{1e90}', ['\u{1e91}', '\0', '\0']), ('\u{1e92}', ['\u{1e93}', '\0', '\0']), ('\u{1e94}',
-        ['\u{1e95}', '\0', '\0']), ('\u{1e9e}', ['\u{df}', '\0', '\0']), ('\u{1ea0}', ['\u{1ea1}',
-        '\0', '\0']), ('\u{1ea2}', ['\u{1ea3}', '\0', '\0']), ('\u{1ea4}', ['\u{1ea5}', '\0',
-        '\0']), ('\u{1ea6}', ['\u{1ea7}', '\0', '\0']), ('\u{1ea8}', ['\u{1ea9}', '\0', '\0']),
-        ('\u{1eaa}', ['\u{1eab}', '\0', '\0']), ('\u{1eac}', ['\u{1ead}', '\0', '\0']), ('\u{1eae}',
-        ['\u{1eaf}', '\0', '\0']), ('\u{1eb0}', ['\u{1eb1}', '\0', '\0']), ('\u{1eb2}', ['\u{1eb3}',
-        '\0', '\0']), ('\u{1eb4}', ['\u{1eb5}', '\0', '\0']), ('\u{1eb6}', ['\u{1eb7}', '\0',
-        '\0']), ('\u{1eb8}', ['\u{1eb9}', '\0', '\0']), ('\u{1eba}', ['\u{1ebb}', '\0', '\0']),
-        ('\u{1ebc}', ['\u{1ebd}', '\0', '\0']), ('\u{1ebe}', ['\u{1ebf}', '\0', '\0']), ('\u{1ec0}',
-        ['\u{1ec1}', '\0', '\0']), ('\u{1ec2}', ['\u{1ec3}', '\0', '\0']), ('\u{1ec4}', ['\u{1ec5}',
-        '\0', '\0']), ('\u{1ec6}', ['\u{1ec7}', '\0', '\0']), ('\u{1ec8}', ['\u{1ec9}', '\0',
-        '\0']), ('\u{1eca}', ['\u{1ecb}', '\0', '\0']), ('\u{1ecc}', ['\u{1ecd}', '\0', '\0']),
-        ('\u{1ece}', ['\u{1ecf}', '\0', '\0']), ('\u{1ed0}', ['\u{1ed1}', '\0', '\0']), ('\u{1ed2}',
-        ['\u{1ed3}', '\0', '\0']), ('\u{1ed4}', ['\u{1ed5}', '\0', '\0']), ('\u{1ed6}', ['\u{1ed7}',
-        '\0', '\0']), ('\u{1ed8}', ['\u{1ed9}', '\0', '\0']), ('\u{1eda}', ['\u{1edb}', '\0',
-        '\0']), ('\u{1edc}', ['\u{1edd}', '\0', '\0']), ('\u{1ede}', ['\u{1edf}', '\0', '\0']),
-        ('\u{1ee0}', ['\u{1ee1}', '\0', '\0']), ('\u{1ee2}', ['\u{1ee3}', '\0', '\0']), ('\u{1ee4}',
-        ['\u{1ee5}', '\0', '\0']), ('\u{1ee6}', ['\u{1ee7}', '\0', '\0']), ('\u{1ee8}', ['\u{1ee9}',
-        '\0', '\0']), ('\u{1eea}', ['\u{1eeb}', '\0', '\0']), ('\u{1eec}', ['\u{1eed}', '\0',
-        '\0']), ('\u{1eee}', ['\u{1eef}', '\0', '\0']), ('\u{1ef0}', ['\u{1ef1}', '\0', '\0']),
-        ('\u{1ef2}', ['\u{1ef3}', '\0', '\0']), ('\u{1ef4}', ['\u{1ef5}', '\0', '\0']), ('\u{1ef6}',
-        ['\u{1ef7}', '\0', '\0']), ('\u{1ef8}', ['\u{1ef9}', '\0', '\0']), ('\u{1efa}', ['\u{1efb}',
-        '\0', '\0']), ('\u{1efc}', ['\u{1efd}', '\0', '\0']), ('\u{1efe}', ['\u{1eff}', '\0',
-        '\0']), ('\u{1f08}', ['\u{1f00}', '\0', '\0']), ('\u{1f09}', ['\u{1f01}', '\0', '\0']),
-        ('\u{1f0a}', ['\u{1f02}', '\0', '\0']), ('\u{1f0b}', ['\u{1f03}', '\0', '\0']), ('\u{1f0c}',
-        ['\u{1f04}', '\0', '\0']), ('\u{1f0d}', ['\u{1f05}', '\0', '\0']), ('\u{1f0e}', ['\u{1f06}',
-        '\0', '\0']), ('\u{1f0f}', ['\u{1f07}', '\0', '\0']), ('\u{1f18}', ['\u{1f10}', '\0',
-        '\0']), ('\u{1f19}', ['\u{1f11}', '\0', '\0']), ('\u{1f1a}', ['\u{1f12}', '\0', '\0']),
-        ('\u{1f1b}', ['\u{1f13}', '\0', '\0']), ('\u{1f1c}', ['\u{1f14}', '\0', '\0']), ('\u{1f1d}',
-        ['\u{1f15}', '\0', '\0']), ('\u{1f28}', ['\u{1f20}', '\0', '\0']), ('\u{1f29}', ['\u{1f21}',
-        '\0', '\0']), ('\u{1f2a}', ['\u{1f22}', '\0', '\0']), ('\u{1f2b}', ['\u{1f23}', '\0',
-        '\0']), ('\u{1f2c}', ['\u{1f24}', '\0', '\0']), ('\u{1f2d}', ['\u{1f25}', '\0', '\0']),
-        ('\u{1f2e}', ['\u{1f26}', '\0', '\0']), ('\u{1f2f}', ['\u{1f27}', '\0', '\0']), ('\u{1f38}',
-        ['\u{1f30}', '\0', '\0']), ('\u{1f39}', ['\u{1f31}', '\0', '\0']), ('\u{1f3a}', ['\u{1f32}',
-        '\0', '\0']), ('\u{1f3b}', ['\u{1f33}', '\0', '\0']), ('\u{1f3c}', ['\u{1f34}', '\0',
-        '\0']), ('\u{1f3d}', ['\u{1f35}', '\0', '\0']), ('\u{1f3e}', ['\u{1f36}', '\0', '\0']),
-        ('\u{1f3f}', ['\u{1f37}', '\0', '\0']), ('\u{1f48}', ['\u{1f40}', '\0', '\0']), ('\u{1f49}',
-        ['\u{1f41}', '\0', '\0']), ('\u{1f4a}', ['\u{1f42}', '\0', '\0']), ('\u{1f4b}', ['\u{1f43}',
-        '\0', '\0']), ('\u{1f4c}', ['\u{1f44}', '\0', '\0']), ('\u{1f4d}', ['\u{1f45}', '\0',
-        '\0']), ('\u{1f59}', ['\u{1f51}', '\0', '\0']), ('\u{1f5b}', ['\u{1f53}', '\0', '\0']),
-        ('\u{1f5d}', ['\u{1f55}', '\0', '\0']), ('\u{1f5f}', ['\u{1f57}', '\0', '\0']), ('\u{1f68}',
-        ['\u{1f60}', '\0', '\0']), ('\u{1f69}', ['\u{1f61}', '\0', '\0']), ('\u{1f6a}', ['\u{1f62}',
-        '\0', '\0']), ('\u{1f6b}', ['\u{1f63}', '\0', '\0']), ('\u{1f6c}', ['\u{1f64}', '\0',
-        '\0']), ('\u{1f6d}', ['\u{1f65}', '\0', '\0']), ('\u{1f6e}', ['\u{1f66}', '\0', '\0']),
-        ('\u{1f6f}', ['\u{1f67}', '\0', '\0']), ('\u{1f88}', ['\u{1f80}', '\0', '\0']), ('\u{1f89}',
-        ['\u{1f81}', '\0', '\0']), ('\u{1f8a}', ['\u{1f82}', '\0', '\0']), ('\u{1f8b}', ['\u{1f83}',
-        '\0', '\0']), ('\u{1f8c}', ['\u{1f84}', '\0', '\0']), ('\u{1f8d}', ['\u{1f85}', '\0',
-        '\0']), ('\u{1f8e}', ['\u{1f86}', '\0', '\0']), ('\u{1f8f}', ['\u{1f87}', '\0', '\0']),
-        ('\u{1f98}', ['\u{1f90}', '\0', '\0']), ('\u{1f99}', ['\u{1f91}', '\0', '\0']), ('\u{1f9a}',
-        ['\u{1f92}', '\0', '\0']), ('\u{1f9b}', ['\u{1f93}', '\0', '\0']), ('\u{1f9c}', ['\u{1f94}',
-        '\0', '\0']), ('\u{1f9d}', ['\u{1f95}', '\0', '\0']), ('\u{1f9e}', ['\u{1f96}', '\0',
-        '\0']), ('\u{1f9f}', ['\u{1f97}', '\0', '\0']), ('\u{1fa8}', ['\u{1fa0}', '\0', '\0']),
-        ('\u{1fa9}', ['\u{1fa1}', '\0', '\0']), ('\u{1faa}', ['\u{1fa2}', '\0', '\0']), ('\u{1fab}',
-        ['\u{1fa3}', '\0', '\0']), ('\u{1fac}', ['\u{1fa4}', '\0', '\0']), ('\u{1fad}', ['\u{1fa5}',
-        '\0', '\0']), ('\u{1fae}', ['\u{1fa6}', '\0', '\0']), ('\u{1faf}', ['\u{1fa7}', '\0',
-        '\0']), ('\u{1fb8}', ['\u{1fb0}', '\0', '\0']), ('\u{1fb9}', ['\u{1fb1}', '\0', '\0']),
-        ('\u{1fba}', ['\u{1f70}', '\0', '\0']), ('\u{1fbb}', ['\u{1f71}', '\0', '\0']), ('\u{1fbc}',
-        ['\u{1fb3}', '\0', '\0']), ('\u{1fc8}', ['\u{1f72}', '\0', '\0']), ('\u{1fc9}', ['\u{1f73}',
-        '\0', '\0']), ('\u{1fca}', ['\u{1f74}', '\0', '\0']), ('\u{1fcb}', ['\u{1f75}', '\0',
-        '\0']), ('\u{1fcc}', ['\u{1fc3}', '\0', '\0']), ('\u{1fd8}', ['\u{1fd0}', '\0', '\0']),
-        ('\u{1fd9}', ['\u{1fd1}', '\0', '\0']), ('\u{1fda}', ['\u{1f76}', '\0', '\0']), ('\u{1fdb}',
-        ['\u{1f77}', '\0', '\0']), ('\u{1fe8}', ['\u{1fe0}', '\0', '\0']), ('\u{1fe9}', ['\u{1fe1}',
-        '\0', '\0']), ('\u{1fea}', ['\u{1f7a}', '\0', '\0']), ('\u{1feb}', ['\u{1f7b}', '\0',
-        '\0']), ('\u{1fec}', ['\u{1fe5}', '\0', '\0']), ('\u{1ff8}', ['\u{1f78}', '\0', '\0']),
-        ('\u{1ff9}', ['\u{1f79}', '\0', '\0']), ('\u{1ffa}', ['\u{1f7c}', '\0', '\0']), ('\u{1ffb}',
-        ['\u{1f7d}', '\0', '\0']), ('\u{1ffc}', ['\u{1ff3}', '\0', '\0']), ('\u{2126}', ['\u{3c9}',
-        '\0', '\0']), ('\u{212a}', ['\u{6b}', '\0', '\0']), ('\u{212b}', ['\u{e5}', '\0', '\0']),
-        ('\u{2132}', ['\u{214e}', '\0', '\0']), ('\u{2160}', ['\u{2170}', '\0', '\0']), ('\u{2161}',
-        ['\u{2171}', '\0', '\0']), ('\u{2162}', ['\u{2172}', '\0', '\0']), ('\u{2163}', ['\u{2173}',
-        '\0', '\0']), ('\u{2164}', ['\u{2174}', '\0', '\0']), ('\u{2165}', ['\u{2175}', '\0',
-        '\0']), ('\u{2166}', ['\u{2176}', '\0', '\0']), ('\u{2167}', ['\u{2177}', '\0', '\0']),
-        ('\u{2168}', ['\u{2178}', '\0', '\0']), ('\u{2169}', ['\u{2179}', '\0', '\0']), ('\u{216a}',
-        ['\u{217a}', '\0', '\0']), ('\u{216b}', ['\u{217b}', '\0', '\0']), ('\u{216c}', ['\u{217c}',
-        '\0', '\0']), ('\u{216d}', ['\u{217d}', '\0', '\0']), ('\u{216e}', ['\u{217e}', '\0',
-        '\0']), ('\u{216f}', ['\u{217f}', '\0', '\0']), ('\u{2183}', ['\u{2184}', '\0', '\0']),
-        ('\u{24b6}', ['\u{24d0}', '\0', '\0']), ('\u{24b7}', ['\u{24d1}', '\0', '\0']), ('\u{24b8}',
-        ['\u{24d2}', '\0', '\0']), ('\u{24b9}', ['\u{24d3}', '\0', '\0']), ('\u{24ba}', ['\u{24d4}',
-        '\0', '\0']), ('\u{24bb}', ['\u{24d5}', '\0', '\0']), ('\u{24bc}', ['\u{24d6}', '\0',
-        '\0']), ('\u{24bd}', ['\u{24d7}', '\0', '\0']), ('\u{24be}', ['\u{24d8}', '\0', '\0']),
-        ('\u{24bf}', ['\u{24d9}', '\0', '\0']), ('\u{24c0}', ['\u{24da}', '\0', '\0']), ('\u{24c1}',
-        ['\u{24db}', '\0', '\0']), ('\u{24c2}', ['\u{24dc}', '\0', '\0']), ('\u{24c3}', ['\u{24dd}',
-        '\0', '\0']), ('\u{24c4}', ['\u{24de}', '\0', '\0']), ('\u{24c5}', ['\u{24df}', '\0',
-        '\0']), ('\u{24c6}', ['\u{24e0}', '\0', '\0']), ('\u{24c7}', ['\u{24e1}', '\0', '\0']),
-        ('\u{24c8}', ['\u{24e2}', '\0', '\0']), ('\u{24c9}', ['\u{24e3}', '\0', '\0']), ('\u{24ca}',
-        ['\u{24e4}', '\0', '\0']), ('\u{24cb}', ['\u{24e5}', '\0', '\0']), ('\u{24cc}', ['\u{24e6}',
-        '\0', '\0']), ('\u{24cd}', ['\u{24e7}', '\0', '\0']), ('\u{24ce}', ['\u{24e8}', '\0',
-        '\0']), ('\u{24cf}', ['\u{24e9}', '\0', '\0']), ('\u{2c00}', ['\u{2c30}', '\0', '\0']),
-        ('\u{2c01}', ['\u{2c31}', '\0', '\0']), ('\u{2c02}', ['\u{2c32}', '\0', '\0']), ('\u{2c03}',
-        ['\u{2c33}', '\0', '\0']), ('\u{2c04}', ['\u{2c34}', '\0', '\0']), ('\u{2c05}', ['\u{2c35}',
-        '\0', '\0']), ('\u{2c06}', ['\u{2c36}', '\0', '\0']), ('\u{2c07}', ['\u{2c37}', '\0',
-        '\0']), ('\u{2c08}', ['\u{2c38}', '\0', '\0']), ('\u{2c09}', ['\u{2c39}', '\0', '\0']),
-        ('\u{2c0a}', ['\u{2c3a}', '\0', '\0']), ('\u{2c0b}', ['\u{2c3b}', '\0', '\0']), ('\u{2c0c}',
-        ['\u{2c3c}', '\0', '\0']), ('\u{2c0d}', ['\u{2c3d}', '\0', '\0']), ('\u{2c0e}', ['\u{2c3e}',
-        '\0', '\0']), ('\u{2c0f}', ['\u{2c3f}', '\0', '\0']), ('\u{2c10}', ['\u{2c40}', '\0',
-        '\0']), ('\u{2c11}', ['\u{2c41}', '\0', '\0']), ('\u{2c12}', ['\u{2c42}', '\0', '\0']),
-        ('\u{2c13}', ['\u{2c43}', '\0', '\0']), ('\u{2c14}', ['\u{2c44}', '\0', '\0']), ('\u{2c15}',
-        ['\u{2c45}', '\0', '\0']), ('\u{2c16}', ['\u{2c46}', '\0', '\0']), ('\u{2c17}', ['\u{2c47}',
-        '\0', '\0']), ('\u{2c18}', ['\u{2c48}', '\0', '\0']), ('\u{2c19}', ['\u{2c49}', '\0',
-        '\0']), ('\u{2c1a}', ['\u{2c4a}', '\0', '\0']), ('\u{2c1b}', ['\u{2c4b}', '\0', '\0']),
-        ('\u{2c1c}', ['\u{2c4c}', '\0', '\0']), ('\u{2c1d}', ['\u{2c4d}', '\0', '\0']), ('\u{2c1e}',
-        ['\u{2c4e}', '\0', '\0']), ('\u{2c1f}', ['\u{2c4f}', '\0', '\0']), ('\u{2c20}', ['\u{2c50}',
-        '\0', '\0']), ('\u{2c21}', ['\u{2c51}', '\0', '\0']), ('\u{2c22}', ['\u{2c52}', '\0',
-        '\0']), ('\u{2c23}', ['\u{2c53}', '\0', '\0']), ('\u{2c24}', ['\u{2c54}', '\0', '\0']),
-        ('\u{2c25}', ['\u{2c55}', '\0', '\0']), ('\u{2c26}', ['\u{2c56}', '\0', '\0']), ('\u{2c27}',
-        ['\u{2c57}', '\0', '\0']), ('\u{2c28}', ['\u{2c58}', '\0', '\0']), ('\u{2c29}', ['\u{2c59}',
-        '\0', '\0']), ('\u{2c2a}', ['\u{2c5a}', '\0', '\0']), ('\u{2c2b}', ['\u{2c5b}', '\0',
-        '\0']), ('\u{2c2c}', ['\u{2c5c}', '\0', '\0']), ('\u{2c2d}', ['\u{2c5d}', '\0', '\0']),
-        ('\u{2c2e}', ['\u{2c5e}', '\0', '\0']), ('\u{2c60}', ['\u{2c61}', '\0', '\0']), ('\u{2c62}',
-        ['\u{26b}', '\0', '\0']), ('\u{2c63}', ['\u{1d7d}', '\0', '\0']), ('\u{2c64}', ['\u{27d}',
-        '\0', '\0']), ('\u{2c67}', ['\u{2c68}', '\0', '\0']), ('\u{2c69}', ['\u{2c6a}', '\0',
-        '\0']), ('\u{2c6b}', ['\u{2c6c}', '\0', '\0']), ('\u{2c6d}', ['\u{251}', '\0', '\0']),
-        ('\u{2c6e}', ['\u{271}', '\0', '\0']), ('\u{2c6f}', ['\u{250}', '\0', '\0']), ('\u{2c70}',
-        ['\u{252}', '\0', '\0']), ('\u{2c72}', ['\u{2c73}', '\0', '\0']), ('\u{2c75}', ['\u{2c76}',
-        '\0', '\0']), ('\u{2c7e}', ['\u{23f}', '\0', '\0']), ('\u{2c7f}', ['\u{240}', '\0', '\0']),
-        ('\u{2c80}', ['\u{2c81}', '\0', '\0']), ('\u{2c82}', ['\u{2c83}', '\0', '\0']), ('\u{2c84}',
-        ['\u{2c85}', '\0', '\0']), ('\u{2c86}', ['\u{2c87}', '\0', '\0']), ('\u{2c88}', ['\u{2c89}',
-        '\0', '\0']), ('\u{2c8a}', ['\u{2c8b}', '\0', '\0']), ('\u{2c8c}', ['\u{2c8d}', '\0',
-        '\0']), ('\u{2c8e}', ['\u{2c8f}', '\0', '\0']), ('\u{2c90}', ['\u{2c91}', '\0', '\0']),
-        ('\u{2c92}', ['\u{2c93}', '\0', '\0']), ('\u{2c94}', ['\u{2c95}', '\0', '\0']), ('\u{2c96}',
-        ['\u{2c97}', '\0', '\0']), ('\u{2c98}', ['\u{2c99}', '\0', '\0']), ('\u{2c9a}', ['\u{2c9b}',
-        '\0', '\0']), ('\u{2c9c}', ['\u{2c9d}', '\0', '\0']), ('\u{2c9e}', ['\u{2c9f}', '\0',
-        '\0']), ('\u{2ca0}', ['\u{2ca1}', '\0', '\0']), ('\u{2ca2}', ['\u{2ca3}', '\0', '\0']),
-        ('\u{2ca4}', ['\u{2ca5}', '\0', '\0']), ('\u{2ca6}', ['\u{2ca7}', '\0', '\0']), ('\u{2ca8}',
-        ['\u{2ca9}', '\0', '\0']), ('\u{2caa}', ['\u{2cab}', '\0', '\0']), ('\u{2cac}', ['\u{2cad}',
-        '\0', '\0']), ('\u{2cae}', ['\u{2caf}', '\0', '\0']), ('\u{2cb0}', ['\u{2cb1}', '\0',
-        '\0']), ('\u{2cb2}', ['\u{2cb3}', '\0', '\0']), ('\u{2cb4}', ['\u{2cb5}', '\0', '\0']),
-        ('\u{2cb6}', ['\u{2cb7}', '\0', '\0']), ('\u{2cb8}', ['\u{2cb9}', '\0', '\0']), ('\u{2cba}',
-        ['\u{2cbb}', '\0', '\0']), ('\u{2cbc}', ['\u{2cbd}', '\0', '\0']), ('\u{2cbe}', ['\u{2cbf}',
-        '\0', '\0']), ('\u{2cc0}', ['\u{2cc1}', '\0', '\0']), ('\u{2cc2}', ['\u{2cc3}', '\0',
-        '\0']), ('\u{2cc4}', ['\u{2cc5}', '\0', '\0']), ('\u{2cc6}', ['\u{2cc7}', '\0', '\0']),
-        ('\u{2cc8}', ['\u{2cc9}', '\0', '\0']), ('\u{2cca}', ['\u{2ccb}', '\0', '\0']), ('\u{2ccc}',
-        ['\u{2ccd}', '\0', '\0']), ('\u{2cce}', ['\u{2ccf}', '\0', '\0']), ('\u{2cd0}', ['\u{2cd1}',
-        '\0', '\0']), ('\u{2cd2}', ['\u{2cd3}', '\0', '\0']), ('\u{2cd4}', ['\u{2cd5}', '\0',
-        '\0']), ('\u{2cd6}', ['\u{2cd7}', '\0', '\0']), ('\u{2cd8}', ['\u{2cd9}', '\0', '\0']),
-        ('\u{2cda}', ['\u{2cdb}', '\0', '\0']), ('\u{2cdc}', ['\u{2cdd}', '\0', '\0']), ('\u{2cde}',
-        ['\u{2cdf}', '\0', '\0']), ('\u{2ce0}', ['\u{2ce1}', '\0', '\0']), ('\u{2ce2}', ['\u{2ce3}',
-        '\0', '\0']), ('\u{2ceb}', ['\u{2cec}', '\0', '\0']), ('\u{2ced}', ['\u{2cee}', '\0',
-        '\0']), ('\u{2cf2}', ['\u{2cf3}', '\0', '\0']), ('\u{a640}', ['\u{a641}', '\0', '\0']),
-        ('\u{a642}', ['\u{a643}', '\0', '\0']), ('\u{a644}', ['\u{a645}', '\0', '\0']), ('\u{a646}',
-        ['\u{a647}', '\0', '\0']), ('\u{a648}', ['\u{a649}', '\0', '\0']), ('\u{a64a}', ['\u{a64b}',
-        '\0', '\0']), ('\u{a64c}', ['\u{a64d}', '\0', '\0']), ('\u{a64e}', ['\u{a64f}', '\0',
-        '\0']), ('\u{a650}', ['\u{a651}', '\0', '\0']), ('\u{a652}', ['\u{a653}', '\0', '\0']),
-        ('\u{a654}', ['\u{a655}', '\0', '\0']), ('\u{a656}', ['\u{a657}', '\0', '\0']), ('\u{a658}',
-        ['\u{a659}', '\0', '\0']), ('\u{a65a}', ['\u{a65b}', '\0', '\0']), ('\u{a65c}', ['\u{a65d}',
-        '\0', '\0']), ('\u{a65e}', ['\u{a65f}', '\0', '\0']), ('\u{a660}', ['\u{a661}', '\0',
-        '\0']), ('\u{a662}', ['\u{a663}', '\0', '\0']), ('\u{a664}', ['\u{a665}', '\0', '\0']),
-        ('\u{a666}', ['\u{a667}', '\0', '\0']), ('\u{a668}', ['\u{a669}', '\0', '\0']), ('\u{a66a}',
-        ['\u{a66b}', '\0', '\0']), ('\u{a66c}', ['\u{a66d}', '\0', '\0']), ('\u{a680}', ['\u{a681}',
-        '\0', '\0']), ('\u{a682}', ['\u{a683}', '\0', '\0']), ('\u{a684}', ['\u{a685}', '\0',
-        '\0']), ('\u{a686}', ['\u{a687}', '\0', '\0']), ('\u{a688}', ['\u{a689}', '\0', '\0']),
-        ('\u{a68a}', ['\u{a68b}', '\0', '\0']), ('\u{a68c}', ['\u{a68d}', '\0', '\0']), ('\u{a68e}',
-        ['\u{a68f}', '\0', '\0']), ('\u{a690}', ['\u{a691}', '\0', '\0']), ('\u{a692}', ['\u{a693}',
-        '\0', '\0']), ('\u{a694}', ['\u{a695}', '\0', '\0']), ('\u{a696}', ['\u{a697}', '\0',
-        '\0']), ('\u{a698}', ['\u{a699}', '\0', '\0']), ('\u{a69a}', ['\u{a69b}', '\0', '\0']),
-        ('\u{a722}', ['\u{a723}', '\0', '\0']), ('\u{a724}', ['\u{a725}', '\0', '\0']), ('\u{a726}',
-        ['\u{a727}', '\0', '\0']), ('\u{a728}', ['\u{a729}', '\0', '\0']), ('\u{a72a}', ['\u{a72b}',
-        '\0', '\0']), ('\u{a72c}', ['\u{a72d}', '\0', '\0']), ('\u{a72e}', ['\u{a72f}', '\0',
-        '\0']), ('\u{a732}', ['\u{a733}', '\0', '\0']), ('\u{a734}', ['\u{a735}', '\0', '\0']),
-        ('\u{a736}', ['\u{a737}', '\0', '\0']), ('\u{a738}', ['\u{a739}', '\0', '\0']), ('\u{a73a}',
-        ['\u{a73b}', '\0', '\0']), ('\u{a73c}', ['\u{a73d}', '\0', '\0']), ('\u{a73e}', ['\u{a73f}',
-        '\0', '\0']), ('\u{a740}', ['\u{a741}', '\0', '\0']), ('\u{a742}', ['\u{a743}', '\0',
-        '\0']), ('\u{a744}', ['\u{a745}', '\0', '\0']), ('\u{a746}', ['\u{a747}', '\0', '\0']),
-        ('\u{a748}', ['\u{a749}', '\0', '\0']), ('\u{a74a}', ['\u{a74b}', '\0', '\0']), ('\u{a74c}',
-        ['\u{a74d}', '\0', '\0']), ('\u{a74e}', ['\u{a74f}', '\0', '\0']), ('\u{a750}', ['\u{a751}',
-        '\0', '\0']), ('\u{a752}', ['\u{a753}', '\0', '\0']), ('\u{a754}', ['\u{a755}', '\0',
-        '\0']), ('\u{a756}', ['\u{a757}', '\0', '\0']), ('\u{a758}', ['\u{a759}', '\0', '\0']),
-        ('\u{a75a}', ['\u{a75b}', '\0', '\0']), ('\u{a75c}', ['\u{a75d}', '\0', '\0']), ('\u{a75e}',
-        ['\u{a75f}', '\0', '\0']), ('\u{a760}', ['\u{a761}', '\0', '\0']), ('\u{a762}', ['\u{a763}',
-        '\0', '\0']), ('\u{a764}', ['\u{a765}', '\0', '\0']), ('\u{a766}', ['\u{a767}', '\0',
-        '\0']), ('\u{a768}', ['\u{a769}', '\0', '\0']), ('\u{a76a}', ['\u{a76b}', '\0', '\0']),
-        ('\u{a76c}', ['\u{a76d}', '\0', '\0']), ('\u{a76e}', ['\u{a76f}', '\0', '\0']), ('\u{a779}',
-        ['\u{a77a}', '\0', '\0']), ('\u{a77b}', ['\u{a77c}', '\0', '\0']), ('\u{a77d}', ['\u{1d79}',
-        '\0', '\0']), ('\u{a77e}', ['\u{a77f}', '\0', '\0']), ('\u{a780}', ['\u{a781}', '\0',
-        '\0']), ('\u{a782}', ['\u{a783}', '\0', '\0']), ('\u{a784}', ['\u{a785}', '\0', '\0']),
-        ('\u{a786}', ['\u{a787}', '\0', '\0']), ('\u{a78b}', ['\u{a78c}', '\0', '\0']), ('\u{a78d}',
-        ['\u{265}', '\0', '\0']), ('\u{a790}', ['\u{a791}', '\0', '\0']), ('\u{a792}', ['\u{a793}',
-        '\0', '\0']), ('\u{a796}', ['\u{a797}', '\0', '\0']), ('\u{a798}', ['\u{a799}', '\0',
-        '\0']), ('\u{a79a}', ['\u{a79b}', '\0', '\0']), ('\u{a79c}', ['\u{a79d}', '\0', '\0']),
-        ('\u{a79e}', ['\u{a79f}', '\0', '\0']), ('\u{a7a0}', ['\u{a7a1}', '\0', '\0']), ('\u{a7a2}',
-        ['\u{a7a3}', '\0', '\0']), ('\u{a7a4}', ['\u{a7a5}', '\0', '\0']), ('\u{a7a6}', ['\u{a7a7}',
-        '\0', '\0']), ('\u{a7a8}', ['\u{a7a9}', '\0', '\0']), ('\u{a7aa}', ['\u{266}', '\0', '\0']),
-        ('\u{a7ab}', ['\u{25c}', '\0', '\0']), ('\u{a7ac}', ['\u{261}', '\0', '\0']), ('\u{a7ad}',
-        ['\u{26c}', '\0', '\0']), ('\u{a7ae}', ['\u{26a}', '\0', '\0']), ('\u{a7b0}', ['\u{29e}',
-        '\0', '\0']), ('\u{a7b1}', ['\u{287}', '\0', '\0']), ('\u{a7b2}', ['\u{29d}', '\0', '\0']),
-        ('\u{a7b3}', ['\u{ab53}', '\0', '\0']), ('\u{a7b4}', ['\u{a7b5}', '\0', '\0']), ('\u{a7b6}',
-        ['\u{a7b7}', '\0', '\0']), ('\u{a7b8}', ['\u{a7b9}', '\0', '\0']), ('\u{a7ba}', ['\u{a7bb}',
-        '\0', '\0']), ('\u{a7bc}', ['\u{a7bd}', '\0', '\0']), ('\u{a7be}', ['\u{a7bf}', '\0',
-        '\0']), ('\u{a7c2}', ['\u{a7c3}', '\0', '\0']), ('\u{a7c4}', ['\u{a794}', '\0', '\0']),
-        ('\u{a7c5}', ['\u{282}', '\0', '\0']), ('\u{a7c6}', ['\u{1d8e}', '\0', '\0']), ('\u{ff21}',
-        ['\u{ff41}', '\0', '\0']), ('\u{ff22}', ['\u{ff42}', '\0', '\0']), ('\u{ff23}', ['\u{ff43}',
-        '\0', '\0']), ('\u{ff24}', ['\u{ff44}', '\0', '\0']), ('\u{ff25}', ['\u{ff45}', '\0',
-        '\0']), ('\u{ff26}', ['\u{ff46}', '\0', '\0']), ('\u{ff27}', ['\u{ff47}', '\0', '\0']),
-        ('\u{ff28}', ['\u{ff48}', '\0', '\0']), ('\u{ff29}', ['\u{ff49}', '\0', '\0']), ('\u{ff2a}',
-        ['\u{ff4a}', '\0', '\0']), ('\u{ff2b}', ['\u{ff4b}', '\0', '\0']), ('\u{ff2c}', ['\u{ff4c}',
-        '\0', '\0']), ('\u{ff2d}', ['\u{ff4d}', '\0', '\0']), ('\u{ff2e}', ['\u{ff4e}', '\0',
-        '\0']), ('\u{ff2f}', ['\u{ff4f}', '\0', '\0']), ('\u{ff30}', ['\u{ff50}', '\0', '\0']),
-        ('\u{ff31}', ['\u{ff51}', '\0', '\0']), ('\u{ff32}', ['\u{ff52}', '\0', '\0']), ('\u{ff33}',
-        ['\u{ff53}', '\0', '\0']), ('\u{ff34}', ['\u{ff54}', '\0', '\0']), ('\u{ff35}', ['\u{ff55}',
-        '\0', '\0']), ('\u{ff36}', ['\u{ff56}', '\0', '\0']), ('\u{ff37}', ['\u{ff57}', '\0',
-        '\0']), ('\u{ff38}', ['\u{ff58}', '\0', '\0']), ('\u{ff39}', ['\u{ff59}', '\0', '\0']),
-        ('\u{ff3a}', ['\u{ff5a}', '\0', '\0']), ('\u{10400}', ['\u{10428}', '\0', '\0']),
-        ('\u{10401}', ['\u{10429}', '\0', '\0']), ('\u{10402}', ['\u{1042a}', '\0', '\0']),
-        ('\u{10403}', ['\u{1042b}', '\0', '\0']), ('\u{10404}', ['\u{1042c}', '\0', '\0']),
-        ('\u{10405}', ['\u{1042d}', '\0', '\0']), ('\u{10406}', ['\u{1042e}', '\0', '\0']),
-        ('\u{10407}', ['\u{1042f}', '\0', '\0']), ('\u{10408}', ['\u{10430}', '\0', '\0']),
-        ('\u{10409}', ['\u{10431}', '\0', '\0']), ('\u{1040a}', ['\u{10432}', '\0', '\0']),
-        ('\u{1040b}', ['\u{10433}', '\0', '\0']), ('\u{1040c}', ['\u{10434}', '\0', '\0']),
-        ('\u{1040d}', ['\u{10435}', '\0', '\0']), ('\u{1040e}', ['\u{10436}', '\0', '\0']),
-        ('\u{1040f}', ['\u{10437}', '\0', '\0']), ('\u{10410}', ['\u{10438}', '\0', '\0']),
-        ('\u{10411}', ['\u{10439}', '\0', '\0']), ('\u{10412}', ['\u{1043a}', '\0', '\0']),
-        ('\u{10413}', ['\u{1043b}', '\0', '\0']), ('\u{10414}', ['\u{1043c}', '\0', '\0']),
-        ('\u{10415}', ['\u{1043d}', '\0', '\0']), ('\u{10416}', ['\u{1043e}', '\0', '\0']),
-        ('\u{10417}', ['\u{1043f}', '\0', '\0']), ('\u{10418}', ['\u{10440}', '\0', '\0']),
-        ('\u{10419}', ['\u{10441}', '\0', '\0']), ('\u{1041a}', ['\u{10442}', '\0', '\0']),
-        ('\u{1041b}', ['\u{10443}', '\0', '\0']), ('\u{1041c}', ['\u{10444}', '\0', '\0']),
-        ('\u{1041d}', ['\u{10445}', '\0', '\0']), ('\u{1041e}', ['\u{10446}', '\0', '\0']),
-        ('\u{1041f}', ['\u{10447}', '\0', '\0']), ('\u{10420}', ['\u{10448}', '\0', '\0']),
-        ('\u{10421}', ['\u{10449}', '\0', '\0']), ('\u{10422}', ['\u{1044a}', '\0', '\0']),
-        ('\u{10423}', ['\u{1044b}', '\0', '\0']), ('\u{10424}', ['\u{1044c}', '\0', '\0']),
-        ('\u{10425}', ['\u{1044d}', '\0', '\0']), ('\u{10426}', ['\u{1044e}', '\0', '\0']),
-        ('\u{10427}', ['\u{1044f}', '\0', '\0']), ('\u{104b0}', ['\u{104d8}', '\0', '\0']),
-        ('\u{104b1}', ['\u{104d9}', '\0', '\0']), ('\u{104b2}', ['\u{104da}', '\0', '\0']),
-        ('\u{104b3}', ['\u{104db}', '\0', '\0']), ('\u{104b4}', ['\u{104dc}', '\0', '\0']),
-        ('\u{104b5}', ['\u{104dd}', '\0', '\0']), ('\u{104b6}', ['\u{104de}', '\0', '\0']),
-        ('\u{104b7}', ['\u{104df}', '\0', '\0']), ('\u{104b8}', ['\u{104e0}', '\0', '\0']),
-        ('\u{104b9}', ['\u{104e1}', '\0', '\0']), ('\u{104ba}', ['\u{104e2}', '\0', '\0']),
-        ('\u{104bb}', ['\u{104e3}', '\0', '\0']), ('\u{104bc}', ['\u{104e4}', '\0', '\0']),
-        ('\u{104bd}', ['\u{104e5}', '\0', '\0']), ('\u{104be}', ['\u{104e6}', '\0', '\0']),
-        ('\u{104bf}', ['\u{104e7}', '\0', '\0']), ('\u{104c0}', ['\u{104e8}', '\0', '\0']),
-        ('\u{104c1}', ['\u{104e9}', '\0', '\0']), ('\u{104c2}', ['\u{104ea}', '\0', '\0']),
-        ('\u{104c3}', ['\u{104eb}', '\0', '\0']), ('\u{104c4}', ['\u{104ec}', '\0', '\0']),
-        ('\u{104c5}', ['\u{104ed}', '\0', '\0']), ('\u{104c6}', ['\u{104ee}', '\0', '\0']),
-        ('\u{104c7}', ['\u{104ef}', '\0', '\0']), ('\u{104c8}', ['\u{104f0}', '\0', '\0']),
-        ('\u{104c9}', ['\u{104f1}', '\0', '\0']), ('\u{104ca}', ['\u{104f2}', '\0', '\0']),
-        ('\u{104cb}', ['\u{104f3}', '\0', '\0']), ('\u{104cc}', ['\u{104f4}', '\0', '\0']),
-        ('\u{104cd}', ['\u{104f5}', '\0', '\0']), ('\u{104ce}', ['\u{104f6}', '\0', '\0']),
-        ('\u{104cf}', ['\u{104f7}', '\0', '\0']), ('\u{104d0}', ['\u{104f8}', '\0', '\0']),
-        ('\u{104d1}', ['\u{104f9}', '\0', '\0']), ('\u{104d2}', ['\u{104fa}', '\0', '\0']),
-        ('\u{104d3}', ['\u{104fb}', '\0', '\0']), ('\u{10c80}', ['\u{10cc0}', '\0', '\0']),
-        ('\u{10c81}', ['\u{10cc1}', '\0', '\0']), ('\u{10c82}', ['\u{10cc2}', '\0', '\0']),
-        ('\u{10c83}', ['\u{10cc3}', '\0', '\0']), ('\u{10c84}', ['\u{10cc4}', '\0', '\0']),
-        ('\u{10c85}', ['\u{10cc5}', '\0', '\0']), ('\u{10c86}', ['\u{10cc6}', '\0', '\0']),
-        ('\u{10c87}', ['\u{10cc7}', '\0', '\0']), ('\u{10c88}', ['\u{10cc8}', '\0', '\0']),
-        ('\u{10c89}', ['\u{10cc9}', '\0', '\0']), ('\u{10c8a}', ['\u{10cca}', '\0', '\0']),
-        ('\u{10c8b}', ['\u{10ccb}', '\0', '\0']), ('\u{10c8c}', ['\u{10ccc}', '\0', '\0']),
-        ('\u{10c8d}', ['\u{10ccd}', '\0', '\0']), ('\u{10c8e}', ['\u{10cce}', '\0', '\0']),
-        ('\u{10c8f}', ['\u{10ccf}', '\0', '\0']), ('\u{10c90}', ['\u{10cd0}', '\0', '\0']),
-        ('\u{10c91}', ['\u{10cd1}', '\0', '\0']), ('\u{10c92}', ['\u{10cd2}', '\0', '\0']),
-        ('\u{10c93}', ['\u{10cd3}', '\0', '\0']), ('\u{10c94}', ['\u{10cd4}', '\0', '\0']),
-        ('\u{10c95}', ['\u{10cd5}', '\0', '\0']), ('\u{10c96}', ['\u{10cd6}', '\0', '\0']),
-        ('\u{10c97}', ['\u{10cd7}', '\0', '\0']), ('\u{10c98}', ['\u{10cd8}', '\0', '\0']),
-        ('\u{10c99}', ['\u{10cd9}', '\0', '\0']), ('\u{10c9a}', ['\u{10cda}', '\0', '\0']),
-        ('\u{10c9b}', ['\u{10cdb}', '\0', '\0']), ('\u{10c9c}', ['\u{10cdc}', '\0', '\0']),
-        ('\u{10c9d}', ['\u{10cdd}', '\0', '\0']), ('\u{10c9e}', ['\u{10cde}', '\0', '\0']),
-        ('\u{10c9f}', ['\u{10cdf}', '\0', '\0']), ('\u{10ca0}', ['\u{10ce0}', '\0', '\0']),
-        ('\u{10ca1}', ['\u{10ce1}', '\0', '\0']), ('\u{10ca2}', ['\u{10ce2}', '\0', '\0']),
-        ('\u{10ca3}', ['\u{10ce3}', '\0', '\0']), ('\u{10ca4}', ['\u{10ce4}', '\0', '\0']),
-        ('\u{10ca5}', ['\u{10ce5}', '\0', '\0']), ('\u{10ca6}', ['\u{10ce6}', '\0', '\0']),
-        ('\u{10ca7}', ['\u{10ce7}', '\0', '\0']), ('\u{10ca8}', ['\u{10ce8}', '\0', '\0']),
-        ('\u{10ca9}', ['\u{10ce9}', '\0', '\0']), ('\u{10caa}', ['\u{10cea}', '\0', '\0']),
-        ('\u{10cab}', ['\u{10ceb}', '\0', '\0']), ('\u{10cac}', ['\u{10cec}', '\0', '\0']),
-        ('\u{10cad}', ['\u{10ced}', '\0', '\0']), ('\u{10cae}', ['\u{10cee}', '\0', '\0']),
-        ('\u{10caf}', ['\u{10cef}', '\0', '\0']), ('\u{10cb0}', ['\u{10cf0}', '\0', '\0']),
-        ('\u{10cb1}', ['\u{10cf1}', '\0', '\0']), ('\u{10cb2}', ['\u{10cf2}', '\0', '\0']),
-        ('\u{118a0}', ['\u{118c0}', '\0', '\0']), ('\u{118a1}', ['\u{118c1}', '\0', '\0']),
-        ('\u{118a2}', ['\u{118c2}', '\0', '\0']), ('\u{118a3}', ['\u{118c3}', '\0', '\0']),
-        ('\u{118a4}', ['\u{118c4}', '\0', '\0']), ('\u{118a5}', ['\u{118c5}', '\0', '\0']),
-        ('\u{118a6}', ['\u{118c6}', '\0', '\0']), ('\u{118a7}', ['\u{118c7}', '\0', '\0']),
-        ('\u{118a8}', ['\u{118c8}', '\0', '\0']), ('\u{118a9}', ['\u{118c9}', '\0', '\0']),
-        ('\u{118aa}', ['\u{118ca}', '\0', '\0']), ('\u{118ab}', ['\u{118cb}', '\0', '\0']),
-        ('\u{118ac}', ['\u{118cc}', '\0', '\0']), ('\u{118ad}', ['\u{118cd}', '\0', '\0']),
-        ('\u{118ae}', ['\u{118ce}', '\0', '\0']), ('\u{118af}', ['\u{118cf}', '\0', '\0']),
-        ('\u{118b0}', ['\u{118d0}', '\0', '\0']), ('\u{118b1}', ['\u{118d1}', '\0', '\0']),
-        ('\u{118b2}', ['\u{118d2}', '\0', '\0']), ('\u{118b3}', ['\u{118d3}', '\0', '\0']),
-        ('\u{118b4}', ['\u{118d4}', '\0', '\0']), ('\u{118b5}', ['\u{118d5}', '\0', '\0']),
-        ('\u{118b6}', ['\u{118d6}', '\0', '\0']), ('\u{118b7}', ['\u{118d7}', '\0', '\0']),
-        ('\u{118b8}', ['\u{118d8}', '\0', '\0']), ('\u{118b9}', ['\u{118d9}', '\0', '\0']),
-        ('\u{118ba}', ['\u{118da}', '\0', '\0']), ('\u{118bb}', ['\u{118db}', '\0', '\0']),
-        ('\u{118bc}', ['\u{118dc}', '\0', '\0']), ('\u{118bd}', ['\u{118dd}', '\0', '\0']),
-        ('\u{118be}', ['\u{118de}', '\0', '\0']), ('\u{118bf}', ['\u{118df}', '\0', '\0']),
-        ('\u{16e40}', ['\u{16e60}', '\0', '\0']), ('\u{16e41}', ['\u{16e61}', '\0', '\0']),
-        ('\u{16e42}', ['\u{16e62}', '\0', '\0']), ('\u{16e43}', ['\u{16e63}', '\0', '\0']),
-        ('\u{16e44}', ['\u{16e64}', '\0', '\0']), ('\u{16e45}', ['\u{16e65}', '\0', '\0']),
-        ('\u{16e46}', ['\u{16e66}', '\0', '\0']), ('\u{16e47}', ['\u{16e67}', '\0', '\0']),
-        ('\u{16e48}', ['\u{16e68}', '\0', '\0']), ('\u{16e49}', ['\u{16e69}', '\0', '\0']),
-        ('\u{16e4a}', ['\u{16e6a}', '\0', '\0']), ('\u{16e4b}', ['\u{16e6b}', '\0', '\0']),
-        ('\u{16e4c}', ['\u{16e6c}', '\0', '\0']), ('\u{16e4d}', ['\u{16e6d}', '\0', '\0']),
-        ('\u{16e4e}', ['\u{16e6e}', '\0', '\0']), ('\u{16e4f}', ['\u{16e6f}', '\0', '\0']),
-        ('\u{16e50}', ['\u{16e70}', '\0', '\0']), ('\u{16e51}', ['\u{16e71}', '\0', '\0']),
-        ('\u{16e52}', ['\u{16e72}', '\0', '\0']), ('\u{16e53}', ['\u{16e73}', '\0', '\0']),
-        ('\u{16e54}', ['\u{16e74}', '\0', '\0']), ('\u{16e55}', ['\u{16e75}', '\0', '\0']),
-        ('\u{16e56}', ['\u{16e76}', '\0', '\0']), ('\u{16e57}', ['\u{16e77}', '\0', '\0']),
-        ('\u{16e58}', ['\u{16e78}', '\0', '\0']), ('\u{16e59}', ['\u{16e79}', '\0', '\0']),
-        ('\u{16e5a}', ['\u{16e7a}', '\0', '\0']), ('\u{16e5b}', ['\u{16e7b}', '\0', '\0']),
-        ('\u{16e5c}', ['\u{16e7c}', '\0', '\0']), ('\u{16e5d}', ['\u{16e7d}', '\0', '\0']),
-        ('\u{16e5e}', ['\u{16e7e}', '\0', '\0']), ('\u{16e5f}', ['\u{16e7f}', '\0', '\0']),
-        ('\u{1e900}', ['\u{1e922}', '\0', '\0']), ('\u{1e901}', ['\u{1e923}', '\0', '\0']),
-        ('\u{1e902}', ['\u{1e924}', '\0', '\0']), ('\u{1e903}', ['\u{1e925}', '\0', '\0']),
-        ('\u{1e904}', ['\u{1e926}', '\0', '\0']), ('\u{1e905}', ['\u{1e927}', '\0', '\0']),
-        ('\u{1e906}', ['\u{1e928}', '\0', '\0']), ('\u{1e907}', ['\u{1e929}', '\0', '\0']),
-        ('\u{1e908}', ['\u{1e92a}', '\0', '\0']), ('\u{1e909}', ['\u{1e92b}', '\0', '\0']),
-        ('\u{1e90a}', ['\u{1e92c}', '\0', '\0']), ('\u{1e90b}', ['\u{1e92d}', '\0', '\0']),
-        ('\u{1e90c}', ['\u{1e92e}', '\0', '\0']), ('\u{1e90d}', ['\u{1e92f}', '\0', '\0']),
-        ('\u{1e90e}', ['\u{1e930}', '\0', '\0']), ('\u{1e90f}', ['\u{1e931}', '\0', '\0']),
-        ('\u{1e910}', ['\u{1e932}', '\0', '\0']), ('\u{1e911}', ['\u{1e933}', '\0', '\0']),
-        ('\u{1e912}', ['\u{1e934}', '\0', '\0']), ('\u{1e913}', ['\u{1e935}', '\0', '\0']),
-        ('\u{1e914}', ['\u{1e936}', '\0', '\0']), ('\u{1e915}', ['\u{1e937}', '\0', '\0']),
-        ('\u{1e916}', ['\u{1e938}', '\0', '\0']), ('\u{1e917}', ['\u{1e939}', '\0', '\0']),
-        ('\u{1e918}', ['\u{1e93a}', '\0', '\0']), ('\u{1e919}', ['\u{1e93b}', '\0', '\0']),
-        ('\u{1e91a}', ['\u{1e93c}', '\0', '\0']), ('\u{1e91b}', ['\u{1e93d}', '\0', '\0']),
-        ('\u{1e91c}', ['\u{1e93e}', '\0', '\0']), ('\u{1e91d}', ['\u{1e93f}', '\0', '\0']),
-        ('\u{1e91e}', ['\u{1e940}', '\0', '\0']), ('\u{1e91f}', ['\u{1e941}', '\0', '\0']),
-        ('\u{1e920}', ['\u{1e942}', '\0', '\0']), ('\u{1e921}', ['\u{1e943}', '\0', '\0'])
-    ];
-
-    #[rustfmt::skip]
-    const to_uppercase_table: &[(char, [char; 3])] = &[
-        ('\u{61}', ['\u{41}', '\0', '\0']), ('\u{62}', ['\u{42}', '\0', '\0']), ('\u{63}',
-        ['\u{43}', '\0', '\0']), ('\u{64}', ['\u{44}', '\0', '\0']), ('\u{65}', ['\u{45}', '\0',
-        '\0']), ('\u{66}', ['\u{46}', '\0', '\0']), ('\u{67}', ['\u{47}', '\0', '\0']), ('\u{68}',
-        ['\u{48}', '\0', '\0']), ('\u{69}', ['\u{49}', '\0', '\0']), ('\u{6a}', ['\u{4a}', '\0',
-        '\0']), ('\u{6b}', ['\u{4b}', '\0', '\0']), ('\u{6c}', ['\u{4c}', '\0', '\0']), ('\u{6d}',
-        ['\u{4d}', '\0', '\0']), ('\u{6e}', ['\u{4e}', '\0', '\0']), ('\u{6f}', ['\u{4f}', '\0',
-        '\0']), ('\u{70}', ['\u{50}', '\0', '\0']), ('\u{71}', ['\u{51}', '\0', '\0']), ('\u{72}',
-        ['\u{52}', '\0', '\0']), ('\u{73}', ['\u{53}', '\0', '\0']), ('\u{74}', ['\u{54}', '\0',
-        '\0']), ('\u{75}', ['\u{55}', '\0', '\0']), ('\u{76}', ['\u{56}', '\0', '\0']), ('\u{77}',
-        ['\u{57}', '\0', '\0']), ('\u{78}', ['\u{58}', '\0', '\0']), ('\u{79}', ['\u{59}', '\0',
-        '\0']), ('\u{7a}', ['\u{5a}', '\0', '\0']), ('\u{b5}', ['\u{39c}', '\0', '\0']), ('\u{df}',
-        ['\u{53}', '\u{53}', '\0']), ('\u{e0}', ['\u{c0}', '\0', '\0']), ('\u{e1}', ['\u{c1}', '\0',
-        '\0']), ('\u{e2}', ['\u{c2}', '\0', '\0']), ('\u{e3}', ['\u{c3}', '\0', '\0']), ('\u{e4}',
-        ['\u{c4}', '\0', '\0']), ('\u{e5}', ['\u{c5}', '\0', '\0']), ('\u{e6}', ['\u{c6}', '\0',
-        '\0']), ('\u{e7}', ['\u{c7}', '\0', '\0']), ('\u{e8}', ['\u{c8}', '\0', '\0']), ('\u{e9}',
-        ['\u{c9}', '\0', '\0']), ('\u{ea}', ['\u{ca}', '\0', '\0']), ('\u{eb}', ['\u{cb}', '\0',
-        '\0']), ('\u{ec}', ['\u{cc}', '\0', '\0']), ('\u{ed}', ['\u{cd}', '\0', '\0']), ('\u{ee}',
-        ['\u{ce}', '\0', '\0']), ('\u{ef}', ['\u{cf}', '\0', '\0']), ('\u{f0}', ['\u{d0}', '\0',
-        '\0']), ('\u{f1}', ['\u{d1}', '\0', '\0']), ('\u{f2}', ['\u{d2}', '\0', '\0']), ('\u{f3}',
-        ['\u{d3}', '\0', '\0']), ('\u{f4}', ['\u{d4}', '\0', '\0']), ('\u{f5}', ['\u{d5}', '\0',
-        '\0']), ('\u{f6}', ['\u{d6}', '\0', '\0']), ('\u{f8}', ['\u{d8}', '\0', '\0']), ('\u{f9}',
-        ['\u{d9}', '\0', '\0']), ('\u{fa}', ['\u{da}', '\0', '\0']), ('\u{fb}', ['\u{db}', '\0',
-        '\0']), ('\u{fc}', ['\u{dc}', '\0', '\0']), ('\u{fd}', ['\u{dd}', '\0', '\0']), ('\u{fe}',
-        ['\u{de}', '\0', '\0']), ('\u{ff}', ['\u{178}', '\0', '\0']), ('\u{101}', ['\u{100}', '\0',
-        '\0']), ('\u{103}', ['\u{102}', '\0', '\0']), ('\u{105}', ['\u{104}', '\0', '\0']),
-        ('\u{107}', ['\u{106}', '\0', '\0']), ('\u{109}', ['\u{108}', '\0', '\0']), ('\u{10b}',
-        ['\u{10a}', '\0', '\0']), ('\u{10d}', ['\u{10c}', '\0', '\0']), ('\u{10f}', ['\u{10e}',
-        '\0', '\0']), ('\u{111}', ['\u{110}', '\0', '\0']), ('\u{113}', ['\u{112}', '\0', '\0']),
-        ('\u{115}', ['\u{114}', '\0', '\0']), ('\u{117}', ['\u{116}', '\0', '\0']), ('\u{119}',
-        ['\u{118}', '\0', '\0']), ('\u{11b}', ['\u{11a}', '\0', '\0']), ('\u{11d}', ['\u{11c}',
-        '\0', '\0']), ('\u{11f}', ['\u{11e}', '\0', '\0']), ('\u{121}', ['\u{120}', '\0', '\0']),
-        ('\u{123}', ['\u{122}', '\0', '\0']), ('\u{125}', ['\u{124}', '\0', '\0']), ('\u{127}',
-        ['\u{126}', '\0', '\0']), ('\u{129}', ['\u{128}', '\0', '\0']), ('\u{12b}', ['\u{12a}',
-        '\0', '\0']), ('\u{12d}', ['\u{12c}', '\0', '\0']), ('\u{12f}', ['\u{12e}', '\0', '\0']),
-        ('\u{131}', ['\u{49}', '\0', '\0']), ('\u{133}', ['\u{132}', '\0', '\0']), ('\u{135}',
-        ['\u{134}', '\0', '\0']), ('\u{137}', ['\u{136}', '\0', '\0']), ('\u{13a}', ['\u{139}',
-        '\0', '\0']), ('\u{13c}', ['\u{13b}', '\0', '\0']), ('\u{13e}', ['\u{13d}', '\0', '\0']),
-        ('\u{140}', ['\u{13f}', '\0', '\0']), ('\u{142}', ['\u{141}', '\0', '\0']), ('\u{144}',
-        ['\u{143}', '\0', '\0']), ('\u{146}', ['\u{145}', '\0', '\0']), ('\u{148}', ['\u{147}',
-        '\0', '\0']), ('\u{149}', ['\u{2bc}', '\u{4e}', '\0']), ('\u{14b}', ['\u{14a}', '\0',
-        '\0']), ('\u{14d}', ['\u{14c}', '\0', '\0']), ('\u{14f}', ['\u{14e}', '\0', '\0']),
-        ('\u{151}', ['\u{150}', '\0', '\0']), ('\u{153}', ['\u{152}', '\0', '\0']), ('\u{155}',
-        ['\u{154}', '\0', '\0']), ('\u{157}', ['\u{156}', '\0', '\0']), ('\u{159}', ['\u{158}',
-        '\0', '\0']), ('\u{15b}', ['\u{15a}', '\0', '\0']), ('\u{15d}', ['\u{15c}', '\0', '\0']),
-        ('\u{15f}', ['\u{15e}', '\0', '\0']), ('\u{161}', ['\u{160}', '\0', '\0']), ('\u{163}',
-        ['\u{162}', '\0', '\0']), ('\u{165}', ['\u{164}', '\0', '\0']), ('\u{167}', ['\u{166}',
-        '\0', '\0']), ('\u{169}', ['\u{168}', '\0', '\0']), ('\u{16b}', ['\u{16a}', '\0', '\0']),
-        ('\u{16d}', ['\u{16c}', '\0', '\0']), ('\u{16f}', ['\u{16e}', '\0', '\0']), ('\u{171}',
-        ['\u{170}', '\0', '\0']), ('\u{173}', ['\u{172}', '\0', '\0']), ('\u{175}', ['\u{174}',
-        '\0', '\0']), ('\u{177}', ['\u{176}', '\0', '\0']), ('\u{17a}', ['\u{179}', '\0', '\0']),
-        ('\u{17c}', ['\u{17b}', '\0', '\0']), ('\u{17e}', ['\u{17d}', '\0', '\0']), ('\u{17f}',
-        ['\u{53}', '\0', '\0']), ('\u{180}', ['\u{243}', '\0', '\0']), ('\u{183}', ['\u{182}', '\0',
-        '\0']), ('\u{185}', ['\u{184}', '\0', '\0']), ('\u{188}', ['\u{187}', '\0', '\0']),
-        ('\u{18c}', ['\u{18b}', '\0', '\0']), ('\u{192}', ['\u{191}', '\0', '\0']), ('\u{195}',
-        ['\u{1f6}', '\0', '\0']), ('\u{199}', ['\u{198}', '\0', '\0']), ('\u{19a}', ['\u{23d}',
-        '\0', '\0']), ('\u{19e}', ['\u{220}', '\0', '\0']), ('\u{1a1}', ['\u{1a0}', '\0', '\0']),
-        ('\u{1a3}', ['\u{1a2}', '\0', '\0']), ('\u{1a5}', ['\u{1a4}', '\0', '\0']), ('\u{1a8}',
-        ['\u{1a7}', '\0', '\0']), ('\u{1ad}', ['\u{1ac}', '\0', '\0']), ('\u{1b0}', ['\u{1af}',
-        '\0', '\0']), ('\u{1b4}', ['\u{1b3}', '\0', '\0']), ('\u{1b6}', ['\u{1b5}', '\0', '\0']),
-        ('\u{1b9}', ['\u{1b8}', '\0', '\0']), ('\u{1bd}', ['\u{1bc}', '\0', '\0']), ('\u{1bf}',
-        ['\u{1f7}', '\0', '\0']), ('\u{1c5}', ['\u{1c4}', '\0', '\0']), ('\u{1c6}', ['\u{1c4}',
-        '\0', '\0']), ('\u{1c8}', ['\u{1c7}', '\0', '\0']), ('\u{1c9}', ['\u{1c7}', '\0', '\0']),
-        ('\u{1cb}', ['\u{1ca}', '\0', '\0']), ('\u{1cc}', ['\u{1ca}', '\0', '\0']), ('\u{1ce}',
-        ['\u{1cd}', '\0', '\0']), ('\u{1d0}', ['\u{1cf}', '\0', '\0']), ('\u{1d2}', ['\u{1d1}',
-        '\0', '\0']), ('\u{1d4}', ['\u{1d3}', '\0', '\0']), ('\u{1d6}', ['\u{1d5}', '\0', '\0']),
-        ('\u{1d8}', ['\u{1d7}', '\0', '\0']), ('\u{1da}', ['\u{1d9}', '\0', '\0']), ('\u{1dc}',
-        ['\u{1db}', '\0', '\0']), ('\u{1dd}', ['\u{18e}', '\0', '\0']), ('\u{1df}', ['\u{1de}',
-        '\0', '\0']), ('\u{1e1}', ['\u{1e0}', '\0', '\0']), ('\u{1e3}', ['\u{1e2}', '\0', '\0']),
-        ('\u{1e5}', ['\u{1e4}', '\0', '\0']), ('\u{1e7}', ['\u{1e6}', '\0', '\0']), ('\u{1e9}',
-        ['\u{1e8}', '\0', '\0']), ('\u{1eb}', ['\u{1ea}', '\0', '\0']), ('\u{1ed}', ['\u{1ec}',
-        '\0', '\0']), ('\u{1ef}', ['\u{1ee}', '\0', '\0']), ('\u{1f0}', ['\u{4a}', '\u{30c}',
-        '\0']), ('\u{1f2}', ['\u{1f1}', '\0', '\0']), ('\u{1f3}', ['\u{1f1}', '\0', '\0']),
-        ('\u{1f5}', ['\u{1f4}', '\0', '\0']), ('\u{1f9}', ['\u{1f8}', '\0', '\0']), ('\u{1fb}',
-        ['\u{1fa}', '\0', '\0']), ('\u{1fd}', ['\u{1fc}', '\0', '\0']), ('\u{1ff}', ['\u{1fe}',
-        '\0', '\0']), ('\u{201}', ['\u{200}', '\0', '\0']), ('\u{203}', ['\u{202}', '\0', '\0']),
-        ('\u{205}', ['\u{204}', '\0', '\0']), ('\u{207}', ['\u{206}', '\0', '\0']), ('\u{209}',
-        ['\u{208}', '\0', '\0']), ('\u{20b}', ['\u{20a}', '\0', '\0']), ('\u{20d}', ['\u{20c}',
-        '\0', '\0']), ('\u{20f}', ['\u{20e}', '\0', '\0']), ('\u{211}', ['\u{210}', '\0', '\0']),
-        ('\u{213}', ['\u{212}', '\0', '\0']), ('\u{215}', ['\u{214}', '\0', '\0']), ('\u{217}',
-        ['\u{216}', '\0', '\0']), ('\u{219}', ['\u{218}', '\0', '\0']), ('\u{21b}', ['\u{21a}',
-        '\0', '\0']), ('\u{21d}', ['\u{21c}', '\0', '\0']), ('\u{21f}', ['\u{21e}', '\0', '\0']),
-        ('\u{223}', ['\u{222}', '\0', '\0']), ('\u{225}', ['\u{224}', '\0', '\0']), ('\u{227}',
-        ['\u{226}', '\0', '\0']), ('\u{229}', ['\u{228}', '\0', '\0']), ('\u{22b}', ['\u{22a}',
-        '\0', '\0']), ('\u{22d}', ['\u{22c}', '\0', '\0']), ('\u{22f}', ['\u{22e}', '\0', '\0']),
-        ('\u{231}', ['\u{230}', '\0', '\0']), ('\u{233}', ['\u{232}', '\0', '\0']), ('\u{23c}',
-        ['\u{23b}', '\0', '\0']), ('\u{23f}', ['\u{2c7e}', '\0', '\0']), ('\u{240}', ['\u{2c7f}',
-        '\0', '\0']), ('\u{242}', ['\u{241}', '\0', '\0']), ('\u{247}', ['\u{246}', '\0', '\0']),
-        ('\u{249}', ['\u{248}', '\0', '\0']), ('\u{24b}', ['\u{24a}', '\0', '\0']), ('\u{24d}',
-        ['\u{24c}', '\0', '\0']), ('\u{24f}', ['\u{24e}', '\0', '\0']), ('\u{250}', ['\u{2c6f}',
-        '\0', '\0']), ('\u{251}', ['\u{2c6d}', '\0', '\0']), ('\u{252}', ['\u{2c70}', '\0', '\0']),
-        ('\u{253}', ['\u{181}', '\0', '\0']), ('\u{254}', ['\u{186}', '\0', '\0']), ('\u{256}',
-        ['\u{189}', '\0', '\0']), ('\u{257}', ['\u{18a}', '\0', '\0']), ('\u{259}', ['\u{18f}',
-        '\0', '\0']), ('\u{25b}', ['\u{190}', '\0', '\0']), ('\u{25c}', ['\u{a7ab}', '\0', '\0']),
-        ('\u{260}', ['\u{193}', '\0', '\0']), ('\u{261}', ['\u{a7ac}', '\0', '\0']), ('\u{263}',
-        ['\u{194}', '\0', '\0']), ('\u{265}', ['\u{a78d}', '\0', '\0']), ('\u{266}', ['\u{a7aa}',
-        '\0', '\0']), ('\u{268}', ['\u{197}', '\0', '\0']), ('\u{269}', ['\u{196}', '\0', '\0']),
-        ('\u{26a}', ['\u{a7ae}', '\0', '\0']), ('\u{26b}', ['\u{2c62}', '\0', '\0']), ('\u{26c}',
-        ['\u{a7ad}', '\0', '\0']), ('\u{26f}', ['\u{19c}', '\0', '\0']), ('\u{271}', ['\u{2c6e}',
-        '\0', '\0']), ('\u{272}', ['\u{19d}', '\0', '\0']), ('\u{275}', ['\u{19f}', '\0', '\0']),
-        ('\u{27d}', ['\u{2c64}', '\0', '\0']), ('\u{280}', ['\u{1a6}', '\0', '\0']), ('\u{282}',
-        ['\u{a7c5}', '\0', '\0']), ('\u{283}', ['\u{1a9}', '\0', '\0']), ('\u{287}', ['\u{a7b1}',
-        '\0', '\0']), ('\u{288}', ['\u{1ae}', '\0', '\0']), ('\u{289}', ['\u{244}', '\0', '\0']),
-        ('\u{28a}', ['\u{1b1}', '\0', '\0']), ('\u{28b}', ['\u{1b2}', '\0', '\0']), ('\u{28c}',
-        ['\u{245}', '\0', '\0']), ('\u{292}', ['\u{1b7}', '\0', '\0']), ('\u{29d}', ['\u{a7b2}',
-        '\0', '\0']), ('\u{29e}', ['\u{a7b0}', '\0', '\0']), ('\u{345}', ['\u{399}', '\0', '\0']),
-        ('\u{371}', ['\u{370}', '\0', '\0']), ('\u{373}', ['\u{372}', '\0', '\0']), ('\u{377}',
-        ['\u{376}', '\0', '\0']), ('\u{37b}', ['\u{3fd}', '\0', '\0']), ('\u{37c}', ['\u{3fe}',
-        '\0', '\0']), ('\u{37d}', ['\u{3ff}', '\0', '\0']), ('\u{390}', ['\u{399}', '\u{308}',
-        '\u{301}']), ('\u{3ac}', ['\u{386}', '\0', '\0']), ('\u{3ad}', ['\u{388}', '\0', '\0']),
-        ('\u{3ae}', ['\u{389}', '\0', '\0']), ('\u{3af}', ['\u{38a}', '\0', '\0']), ('\u{3b0}',
-        ['\u{3a5}', '\u{308}', '\u{301}']), ('\u{3b1}', ['\u{391}', '\0', '\0']), ('\u{3b2}',
-        ['\u{392}', '\0', '\0']), ('\u{3b3}', ['\u{393}', '\0', '\0']), ('\u{3b4}', ['\u{394}',
-        '\0', '\0']), ('\u{3b5}', ['\u{395}', '\0', '\0']), ('\u{3b6}', ['\u{396}', '\0', '\0']),
-        ('\u{3b7}', ['\u{397}', '\0', '\0']), ('\u{3b8}', ['\u{398}', '\0', '\0']), ('\u{3b9}',
-        ['\u{399}', '\0', '\0']), ('\u{3ba}', ['\u{39a}', '\0', '\0']), ('\u{3bb}', ['\u{39b}',
-        '\0', '\0']), ('\u{3bc}', ['\u{39c}', '\0', '\0']), ('\u{3bd}', ['\u{39d}', '\0', '\0']),
-        ('\u{3be}', ['\u{39e}', '\0', '\0']), ('\u{3bf}', ['\u{39f}', '\0', '\0']), ('\u{3c0}',
-        ['\u{3a0}', '\0', '\0']), ('\u{3c1}', ['\u{3a1}', '\0', '\0']), ('\u{3c2}', ['\u{3a3}',
-        '\0', '\0']), ('\u{3c3}', ['\u{3a3}', '\0', '\0']), ('\u{3c4}', ['\u{3a4}', '\0', '\0']),
-        ('\u{3c5}', ['\u{3a5}', '\0', '\0']), ('\u{3c6}', ['\u{3a6}', '\0', '\0']), ('\u{3c7}',
-        ['\u{3a7}', '\0', '\0']), ('\u{3c8}', ['\u{3a8}', '\0', '\0']), ('\u{3c9}', ['\u{3a9}',
-        '\0', '\0']), ('\u{3ca}', ['\u{3aa}', '\0', '\0']), ('\u{3cb}', ['\u{3ab}', '\0', '\0']),
-        ('\u{3cc}', ['\u{38c}', '\0', '\0']), ('\u{3cd}', ['\u{38e}', '\0', '\0']), ('\u{3ce}',
-        ['\u{38f}', '\0', '\0']), ('\u{3d0}', ['\u{392}', '\0', '\0']), ('\u{3d1}', ['\u{398}',
-        '\0', '\0']), ('\u{3d5}', ['\u{3a6}', '\0', '\0']), ('\u{3d6}', ['\u{3a0}', '\0', '\0']),
-        ('\u{3d7}', ['\u{3cf}', '\0', '\0']), ('\u{3d9}', ['\u{3d8}', '\0', '\0']), ('\u{3db}',
-        ['\u{3da}', '\0', '\0']), ('\u{3dd}', ['\u{3dc}', '\0', '\0']), ('\u{3df}', ['\u{3de}',
-        '\0', '\0']), ('\u{3e1}', ['\u{3e0}', '\0', '\0']), ('\u{3e3}', ['\u{3e2}', '\0', '\0']),
-        ('\u{3e5}', ['\u{3e4}', '\0', '\0']), ('\u{3e7}', ['\u{3e6}', '\0', '\0']), ('\u{3e9}',
-        ['\u{3e8}', '\0', '\0']), ('\u{3eb}', ['\u{3ea}', '\0', '\0']), ('\u{3ed}', ['\u{3ec}',
-        '\0', '\0']), ('\u{3ef}', ['\u{3ee}', '\0', '\0']), ('\u{3f0}', ['\u{39a}', '\0', '\0']),
-        ('\u{3f1}', ['\u{3a1}', '\0', '\0']), ('\u{3f2}', ['\u{3f9}', '\0', '\0']), ('\u{3f3}',
-        ['\u{37f}', '\0', '\0']), ('\u{3f5}', ['\u{395}', '\0', '\0']), ('\u{3f8}', ['\u{3f7}',
-        '\0', '\0']), ('\u{3fb}', ['\u{3fa}', '\0', '\0']), ('\u{430}', ['\u{410}', '\0', '\0']),
-        ('\u{431}', ['\u{411}', '\0', '\0']), ('\u{432}', ['\u{412}', '\0', '\0']), ('\u{433}',
-        ['\u{413}', '\0', '\0']), ('\u{434}', ['\u{414}', '\0', '\0']), ('\u{435}', ['\u{415}',
-        '\0', '\0']), ('\u{436}', ['\u{416}', '\0', '\0']), ('\u{437}', ['\u{417}', '\0', '\0']),
-        ('\u{438}', ['\u{418}', '\0', '\0']), ('\u{439}', ['\u{419}', '\0', '\0']), ('\u{43a}',
-        ['\u{41a}', '\0', '\0']), ('\u{43b}', ['\u{41b}', '\0', '\0']), ('\u{43c}', ['\u{41c}',
-        '\0', '\0']), ('\u{43d}', ['\u{41d}', '\0', '\0']), ('\u{43e}', ['\u{41e}', '\0', '\0']),
-        ('\u{43f}', ['\u{41f}', '\0', '\0']), ('\u{440}', ['\u{420}', '\0', '\0']), ('\u{441}',
-        ['\u{421}', '\0', '\0']), ('\u{442}', ['\u{422}', '\0', '\0']), ('\u{443}', ['\u{423}',
-        '\0', '\0']), ('\u{444}', ['\u{424}', '\0', '\0']), ('\u{445}', ['\u{425}', '\0', '\0']),
-        ('\u{446}', ['\u{426}', '\0', '\0']), ('\u{447}', ['\u{427}', '\0', '\0']), ('\u{448}',
-        ['\u{428}', '\0', '\0']), ('\u{449}', ['\u{429}', '\0', '\0']), ('\u{44a}', ['\u{42a}',
-        '\0', '\0']), ('\u{44b}', ['\u{42b}', '\0', '\0']), ('\u{44c}', ['\u{42c}', '\0', '\0']),
-        ('\u{44d}', ['\u{42d}', '\0', '\0']), ('\u{44e}', ['\u{42e}', '\0', '\0']), ('\u{44f}',
-        ['\u{42f}', '\0', '\0']), ('\u{450}', ['\u{400}', '\0', '\0']), ('\u{451}', ['\u{401}',
-        '\0', '\0']), ('\u{452}', ['\u{402}', '\0', '\0']), ('\u{453}', ['\u{403}', '\0', '\0']),
-        ('\u{454}', ['\u{404}', '\0', '\0']), ('\u{455}', ['\u{405}', '\0', '\0']), ('\u{456}',
-        ['\u{406}', '\0', '\0']), ('\u{457}', ['\u{407}', '\0', '\0']), ('\u{458}', ['\u{408}',
-        '\0', '\0']), ('\u{459}', ['\u{409}', '\0', '\0']), ('\u{45a}', ['\u{40a}', '\0', '\0']),
-        ('\u{45b}', ['\u{40b}', '\0', '\0']), ('\u{45c}', ['\u{40c}', '\0', '\0']), ('\u{45d}',
-        ['\u{40d}', '\0', '\0']), ('\u{45e}', ['\u{40e}', '\0', '\0']), ('\u{45f}', ['\u{40f}',
-        '\0', '\0']), ('\u{461}', ['\u{460}', '\0', '\0']), ('\u{463}', ['\u{462}', '\0', '\0']),
-        ('\u{465}', ['\u{464}', '\0', '\0']), ('\u{467}', ['\u{466}', '\0', '\0']), ('\u{469}',
-        ['\u{468}', '\0', '\0']), ('\u{46b}', ['\u{46a}', '\0', '\0']), ('\u{46d}', ['\u{46c}',
-        '\0', '\0']), ('\u{46f}', ['\u{46e}', '\0', '\0']), ('\u{471}', ['\u{470}', '\0', '\0']),
-        ('\u{473}', ['\u{472}', '\0', '\0']), ('\u{475}', ['\u{474}', '\0', '\0']), ('\u{477}',
-        ['\u{476}', '\0', '\0']), ('\u{479}', ['\u{478}', '\0', '\0']), ('\u{47b}', ['\u{47a}',
-        '\0', '\0']), ('\u{47d}', ['\u{47c}', '\0', '\0']), ('\u{47f}', ['\u{47e}', '\0', '\0']),
-        ('\u{481}', ['\u{480}', '\0', '\0']), ('\u{48b}', ['\u{48a}', '\0', '\0']), ('\u{48d}',
-        ['\u{48c}', '\0', '\0']), ('\u{48f}', ['\u{48e}', '\0', '\0']), ('\u{491}', ['\u{490}',
-        '\0', '\0']), ('\u{493}', ['\u{492}', '\0', '\0']), ('\u{495}', ['\u{494}', '\0', '\0']),
-        ('\u{497}', ['\u{496}', '\0', '\0']), ('\u{499}', ['\u{498}', '\0', '\0']), ('\u{49b}',
-        ['\u{49a}', '\0', '\0']), ('\u{49d}', ['\u{49c}', '\0', '\0']), ('\u{49f}', ['\u{49e}',
-        '\0', '\0']), ('\u{4a1}', ['\u{4a0}', '\0', '\0']), ('\u{4a3}', ['\u{4a2}', '\0', '\0']),
-        ('\u{4a5}', ['\u{4a4}', '\0', '\0']), ('\u{4a7}', ['\u{4a6}', '\0', '\0']), ('\u{4a9}',
-        ['\u{4a8}', '\0', '\0']), ('\u{4ab}', ['\u{4aa}', '\0', '\0']), ('\u{4ad}', ['\u{4ac}',
-        '\0', '\0']), ('\u{4af}', ['\u{4ae}', '\0', '\0']), ('\u{4b1}', ['\u{4b0}', '\0', '\0']),
-        ('\u{4b3}', ['\u{4b2}', '\0', '\0']), ('\u{4b5}', ['\u{4b4}', '\0', '\0']), ('\u{4b7}',
-        ['\u{4b6}', '\0', '\0']), ('\u{4b9}', ['\u{4b8}', '\0', '\0']), ('\u{4bb}', ['\u{4ba}',
-        '\0', '\0']), ('\u{4bd}', ['\u{4bc}', '\0', '\0']), ('\u{4bf}', ['\u{4be}', '\0', '\0']),
-        ('\u{4c2}', ['\u{4c1}', '\0', '\0']), ('\u{4c4}', ['\u{4c3}', '\0', '\0']), ('\u{4c6}',
-        ['\u{4c5}', '\0', '\0']), ('\u{4c8}', ['\u{4c7}', '\0', '\0']), ('\u{4ca}', ['\u{4c9}',
-        '\0', '\0']), ('\u{4cc}', ['\u{4cb}', '\0', '\0']), ('\u{4ce}', ['\u{4cd}', '\0', '\0']),
-        ('\u{4cf}', ['\u{4c0}', '\0', '\0']), ('\u{4d1}', ['\u{4d0}', '\0', '\0']), ('\u{4d3}',
-        ['\u{4d2}', '\0', '\0']), ('\u{4d5}', ['\u{4d4}', '\0', '\0']), ('\u{4d7}', ['\u{4d6}',
-        '\0', '\0']), ('\u{4d9}', ['\u{4d8}', '\0', '\0']), ('\u{4db}', ['\u{4da}', '\0', '\0']),
-        ('\u{4dd}', ['\u{4dc}', '\0', '\0']), ('\u{4df}', ['\u{4de}', '\0', '\0']), ('\u{4e1}',
-        ['\u{4e0}', '\0', '\0']), ('\u{4e3}', ['\u{4e2}', '\0', '\0']), ('\u{4e5}', ['\u{4e4}',
-        '\0', '\0']), ('\u{4e7}', ['\u{4e6}', '\0', '\0']), ('\u{4e9}', ['\u{4e8}', '\0', '\0']),
-        ('\u{4eb}', ['\u{4ea}', '\0', '\0']), ('\u{4ed}', ['\u{4ec}', '\0', '\0']), ('\u{4ef}',
-        ['\u{4ee}', '\0', '\0']), ('\u{4f1}', ['\u{4f0}', '\0', '\0']), ('\u{4f3}', ['\u{4f2}',
-        '\0', '\0']), ('\u{4f5}', ['\u{4f4}', '\0', '\0']), ('\u{4f7}', ['\u{4f6}', '\0', '\0']),
-        ('\u{4f9}', ['\u{4f8}', '\0', '\0']), ('\u{4fb}', ['\u{4fa}', '\0', '\0']), ('\u{4fd}',
-        ['\u{4fc}', '\0', '\0']), ('\u{4ff}', ['\u{4fe}', '\0', '\0']), ('\u{501}', ['\u{500}',
-        '\0', '\0']), ('\u{503}', ['\u{502}', '\0', '\0']), ('\u{505}', ['\u{504}', '\0', '\0']),
-        ('\u{507}', ['\u{506}', '\0', '\0']), ('\u{509}', ['\u{508}', '\0', '\0']), ('\u{50b}',
-        ['\u{50a}', '\0', '\0']), ('\u{50d}', ['\u{50c}', '\0', '\0']), ('\u{50f}', ['\u{50e}',
-        '\0', '\0']), ('\u{511}', ['\u{510}', '\0', '\0']), ('\u{513}', ['\u{512}', '\0', '\0']),
-        ('\u{515}', ['\u{514}', '\0', '\0']), ('\u{517}', ['\u{516}', '\0', '\0']), ('\u{519}',
-        ['\u{518}', '\0', '\0']), ('\u{51b}', ['\u{51a}', '\0', '\0']), ('\u{51d}', ['\u{51c}',
-        '\0', '\0']), ('\u{51f}', ['\u{51e}', '\0', '\0']), ('\u{521}', ['\u{520}', '\0', '\0']),
-        ('\u{523}', ['\u{522}', '\0', '\0']), ('\u{525}', ['\u{524}', '\0', '\0']), ('\u{527}',
-        ['\u{526}', '\0', '\0']), ('\u{529}', ['\u{528}', '\0', '\0']), ('\u{52b}', ['\u{52a}',
-        '\0', '\0']), ('\u{52d}', ['\u{52c}', '\0', '\0']), ('\u{52f}', ['\u{52e}', '\0', '\0']),
-        ('\u{561}', ['\u{531}', '\0', '\0']), ('\u{562}', ['\u{532}', '\0', '\0']), ('\u{563}',
-        ['\u{533}', '\0', '\0']), ('\u{564}', ['\u{534}', '\0', '\0']), ('\u{565}', ['\u{535}',
-        '\0', '\0']), ('\u{566}', ['\u{536}', '\0', '\0']), ('\u{567}', ['\u{537}', '\0', '\0']),
-        ('\u{568}', ['\u{538}', '\0', '\0']), ('\u{569}', ['\u{539}', '\0', '\0']), ('\u{56a}',
-        ['\u{53a}', '\0', '\0']), ('\u{56b}', ['\u{53b}', '\0', '\0']), ('\u{56c}', ['\u{53c}',
-        '\0', '\0']), ('\u{56d}', ['\u{53d}', '\0', '\0']), ('\u{56e}', ['\u{53e}', '\0', '\0']),
-        ('\u{56f}', ['\u{53f}', '\0', '\0']), ('\u{570}', ['\u{540}', '\0', '\0']), ('\u{571}',
-        ['\u{541}', '\0', '\0']), ('\u{572}', ['\u{542}', '\0', '\0']), ('\u{573}', ['\u{543}',
-        '\0', '\0']), ('\u{574}', ['\u{544}', '\0', '\0']), ('\u{575}', ['\u{545}', '\0', '\0']),
-        ('\u{576}', ['\u{546}', '\0', '\0']), ('\u{577}', ['\u{547}', '\0', '\0']), ('\u{578}',
-        ['\u{548}', '\0', '\0']), ('\u{579}', ['\u{549}', '\0', '\0']), ('\u{57a}', ['\u{54a}',
-        '\0', '\0']), ('\u{57b}', ['\u{54b}', '\0', '\0']), ('\u{57c}', ['\u{54c}', '\0', '\0']),
-        ('\u{57d}', ['\u{54d}', '\0', '\0']), ('\u{57e}', ['\u{54e}', '\0', '\0']), ('\u{57f}',
-        ['\u{54f}', '\0', '\0']), ('\u{580}', ['\u{550}', '\0', '\0']), ('\u{581}', ['\u{551}',
-        '\0', '\0']), ('\u{582}', ['\u{552}', '\0', '\0']), ('\u{583}', ['\u{553}', '\0', '\0']),
-        ('\u{584}', ['\u{554}', '\0', '\0']), ('\u{585}', ['\u{555}', '\0', '\0']), ('\u{586}',
-        ['\u{556}', '\0', '\0']), ('\u{587}', ['\u{535}', '\u{552}', '\0']), ('\u{10d0}',
-        ['\u{1c90}', '\0', '\0']), ('\u{10d1}', ['\u{1c91}', '\0', '\0']), ('\u{10d2}', ['\u{1c92}',
-        '\0', '\0']), ('\u{10d3}', ['\u{1c93}', '\0', '\0']), ('\u{10d4}', ['\u{1c94}', '\0',
-        '\0']), ('\u{10d5}', ['\u{1c95}', '\0', '\0']), ('\u{10d6}', ['\u{1c96}', '\0', '\0']),
-        ('\u{10d7}', ['\u{1c97}', '\0', '\0']), ('\u{10d8}', ['\u{1c98}', '\0', '\0']), ('\u{10d9}',
-        ['\u{1c99}', '\0', '\0']), ('\u{10da}', ['\u{1c9a}', '\0', '\0']), ('\u{10db}', ['\u{1c9b}',
-        '\0', '\0']), ('\u{10dc}', ['\u{1c9c}', '\0', '\0']), ('\u{10dd}', ['\u{1c9d}', '\0',
-        '\0']), ('\u{10de}', ['\u{1c9e}', '\0', '\0']), ('\u{10df}', ['\u{1c9f}', '\0', '\0']),
-        ('\u{10e0}', ['\u{1ca0}', '\0', '\0']), ('\u{10e1}', ['\u{1ca1}', '\0', '\0']), ('\u{10e2}',
-        ['\u{1ca2}', '\0', '\0']), ('\u{10e3}', ['\u{1ca3}', '\0', '\0']), ('\u{10e4}', ['\u{1ca4}',
-        '\0', '\0']), ('\u{10e5}', ['\u{1ca5}', '\0', '\0']), ('\u{10e6}', ['\u{1ca6}', '\0',
-        '\0']), ('\u{10e7}', ['\u{1ca7}', '\0', '\0']), ('\u{10e8}', ['\u{1ca8}', '\0', '\0']),
-        ('\u{10e9}', ['\u{1ca9}', '\0', '\0']), ('\u{10ea}', ['\u{1caa}', '\0', '\0']), ('\u{10eb}',
-        ['\u{1cab}', '\0', '\0']), ('\u{10ec}', ['\u{1cac}', '\0', '\0']), ('\u{10ed}', ['\u{1cad}',
-        '\0', '\0']), ('\u{10ee}', ['\u{1cae}', '\0', '\0']), ('\u{10ef}', ['\u{1caf}', '\0',
-        '\0']), ('\u{10f0}', ['\u{1cb0}', '\0', '\0']), ('\u{10f1}', ['\u{1cb1}', '\0', '\0']),
-        ('\u{10f2}', ['\u{1cb2}', '\0', '\0']), ('\u{10f3}', ['\u{1cb3}', '\0', '\0']), ('\u{10f4}',
-        ['\u{1cb4}', '\0', '\0']), ('\u{10f5}', ['\u{1cb5}', '\0', '\0']), ('\u{10f6}', ['\u{1cb6}',
-        '\0', '\0']), ('\u{10f7}', ['\u{1cb7}', '\0', '\0']), ('\u{10f8}', ['\u{1cb8}', '\0',
-        '\0']), ('\u{10f9}', ['\u{1cb9}', '\0', '\0']), ('\u{10fa}', ['\u{1cba}', '\0', '\0']),
-        ('\u{10fd}', ['\u{1cbd}', '\0', '\0']), ('\u{10fe}', ['\u{1cbe}', '\0', '\0']), ('\u{10ff}',
-        ['\u{1cbf}', '\0', '\0']), ('\u{13f8}', ['\u{13f0}', '\0', '\0']), ('\u{13f9}', ['\u{13f1}',
-        '\0', '\0']), ('\u{13fa}', ['\u{13f2}', '\0', '\0']), ('\u{13fb}', ['\u{13f3}', '\0',
-        '\0']), ('\u{13fc}', ['\u{13f4}', '\0', '\0']), ('\u{13fd}', ['\u{13f5}', '\0', '\0']),
-        ('\u{1c80}', ['\u{412}', '\0', '\0']), ('\u{1c81}', ['\u{414}', '\0', '\0']), ('\u{1c82}',
-        ['\u{41e}', '\0', '\0']), ('\u{1c83}', ['\u{421}', '\0', '\0']), ('\u{1c84}', ['\u{422}',
-        '\0', '\0']), ('\u{1c85}', ['\u{422}', '\0', '\0']), ('\u{1c86}', ['\u{42a}', '\0', '\0']),
-        ('\u{1c87}', ['\u{462}', '\0', '\0']), ('\u{1c88}', ['\u{a64a}', '\0', '\0']), ('\u{1d79}',
-        ['\u{a77d}', '\0', '\0']), ('\u{1d7d}', ['\u{2c63}', '\0', '\0']), ('\u{1d8e}', ['\u{a7c6}',
-        '\0', '\0']), ('\u{1e01}', ['\u{1e00}', '\0', '\0']), ('\u{1e03}', ['\u{1e02}', '\0',
-        '\0']), ('\u{1e05}', ['\u{1e04}', '\0', '\0']), ('\u{1e07}', ['\u{1e06}', '\0', '\0']),
-        ('\u{1e09}', ['\u{1e08}', '\0', '\0']), ('\u{1e0b}', ['\u{1e0a}', '\0', '\0']), ('\u{1e0d}',
-        ['\u{1e0c}', '\0', '\0']), ('\u{1e0f}', ['\u{1e0e}', '\0', '\0']), ('\u{1e11}', ['\u{1e10}',
-        '\0', '\0']), ('\u{1e13}', ['\u{1e12}', '\0', '\0']), ('\u{1e15}', ['\u{1e14}', '\0',
-        '\0']), ('\u{1e17}', ['\u{1e16}', '\0', '\0']), ('\u{1e19}', ['\u{1e18}', '\0', '\0']),
-        ('\u{1e1b}', ['\u{1e1a}', '\0', '\0']), ('\u{1e1d}', ['\u{1e1c}', '\0', '\0']), ('\u{1e1f}',
-        ['\u{1e1e}', '\0', '\0']), ('\u{1e21}', ['\u{1e20}', '\0', '\0']), ('\u{1e23}', ['\u{1e22}',
-        '\0', '\0']), ('\u{1e25}', ['\u{1e24}', '\0', '\0']), ('\u{1e27}', ['\u{1e26}', '\0',
-        '\0']), ('\u{1e29}', ['\u{1e28}', '\0', '\0']), ('\u{1e2b}', ['\u{1e2a}', '\0', '\0']),
-        ('\u{1e2d}', ['\u{1e2c}', '\0', '\0']), ('\u{1e2f}', ['\u{1e2e}', '\0', '\0']), ('\u{1e31}',
-        ['\u{1e30}', '\0', '\0']), ('\u{1e33}', ['\u{1e32}', '\0', '\0']), ('\u{1e35}', ['\u{1e34}',
-        '\0', '\0']), ('\u{1e37}', ['\u{1e36}', '\0', '\0']), ('\u{1e39}', ['\u{1e38}', '\0',
-        '\0']), ('\u{1e3b}', ['\u{1e3a}', '\0', '\0']), ('\u{1e3d}', ['\u{1e3c}', '\0', '\0']),
-        ('\u{1e3f}', ['\u{1e3e}', '\0', '\0']), ('\u{1e41}', ['\u{1e40}', '\0', '\0']), ('\u{1e43}',
-        ['\u{1e42}', '\0', '\0']), ('\u{1e45}', ['\u{1e44}', '\0', '\0']), ('\u{1e47}', ['\u{1e46}',
-        '\0', '\0']), ('\u{1e49}', ['\u{1e48}', '\0', '\0']), ('\u{1e4b}', ['\u{1e4a}', '\0',
-        '\0']), ('\u{1e4d}', ['\u{1e4c}', '\0', '\0']), ('\u{1e4f}', ['\u{1e4e}', '\0', '\0']),
-        ('\u{1e51}', ['\u{1e50}', '\0', '\0']), ('\u{1e53}', ['\u{1e52}', '\0', '\0']), ('\u{1e55}',
-        ['\u{1e54}', '\0', '\0']), ('\u{1e57}', ['\u{1e56}', '\0', '\0']), ('\u{1e59}', ['\u{1e58}',
-        '\0', '\0']), ('\u{1e5b}', ['\u{1e5a}', '\0', '\0']), ('\u{1e5d}', ['\u{1e5c}', '\0',
-        '\0']), ('\u{1e5f}', ['\u{1e5e}', '\0', '\0']), ('\u{1e61}', ['\u{1e60}', '\0', '\0']),
-        ('\u{1e63}', ['\u{1e62}', '\0', '\0']), ('\u{1e65}', ['\u{1e64}', '\0', '\0']), ('\u{1e67}',
-        ['\u{1e66}', '\0', '\0']), ('\u{1e69}', ['\u{1e68}', '\0', '\0']), ('\u{1e6b}', ['\u{1e6a}',
-        '\0', '\0']), ('\u{1e6d}', ['\u{1e6c}', '\0', '\0']), ('\u{1e6f}', ['\u{1e6e}', '\0',
-        '\0']), ('\u{1e71}', ['\u{1e70}', '\0', '\0']), ('\u{1e73}', ['\u{1e72}', '\0', '\0']),
-        ('\u{1e75}', ['\u{1e74}', '\0', '\0']), ('\u{1e77}', ['\u{1e76}', '\0', '\0']), ('\u{1e79}',
-        ['\u{1e78}', '\0', '\0']), ('\u{1e7b}', ['\u{1e7a}', '\0', '\0']), ('\u{1e7d}', ['\u{1e7c}',
-        '\0', '\0']), ('\u{1e7f}', ['\u{1e7e}', '\0', '\0']), ('\u{1e81}', ['\u{1e80}', '\0',
-        '\0']), ('\u{1e83}', ['\u{1e82}', '\0', '\0']), ('\u{1e85}', ['\u{1e84}', '\0', '\0']),
-        ('\u{1e87}', ['\u{1e86}', '\0', '\0']), ('\u{1e89}', ['\u{1e88}', '\0', '\0']), ('\u{1e8b}',
-        ['\u{1e8a}', '\0', '\0']), ('\u{1e8d}', ['\u{1e8c}', '\0', '\0']), ('\u{1e8f}', ['\u{1e8e}',
-        '\0', '\0']), ('\u{1e91}', ['\u{1e90}', '\0', '\0']), ('\u{1e93}', ['\u{1e92}', '\0',
-        '\0']), ('\u{1e95}', ['\u{1e94}', '\0', '\0']), ('\u{1e96}', ['\u{48}', '\u{331}', '\0']),
-        ('\u{1e97}', ['\u{54}', '\u{308}', '\0']), ('\u{1e98}', ['\u{57}', '\u{30a}', '\0']),
-        ('\u{1e99}', ['\u{59}', '\u{30a}', '\0']), ('\u{1e9a}', ['\u{41}', '\u{2be}', '\0']),
-        ('\u{1e9b}', ['\u{1e60}', '\0', '\0']), ('\u{1ea1}', ['\u{1ea0}', '\0', '\0']), ('\u{1ea3}',
-        ['\u{1ea2}', '\0', '\0']), ('\u{1ea5}', ['\u{1ea4}', '\0', '\0']), ('\u{1ea7}', ['\u{1ea6}',
-        '\0', '\0']), ('\u{1ea9}', ['\u{1ea8}', '\0', '\0']), ('\u{1eab}', ['\u{1eaa}', '\0',
-        '\0']), ('\u{1ead}', ['\u{1eac}', '\0', '\0']), ('\u{1eaf}', ['\u{1eae}', '\0', '\0']),
-        ('\u{1eb1}', ['\u{1eb0}', '\0', '\0']), ('\u{1eb3}', ['\u{1eb2}', '\0', '\0']), ('\u{1eb5}',
-        ['\u{1eb4}', '\0', '\0']), ('\u{1eb7}', ['\u{1eb6}', '\0', '\0']), ('\u{1eb9}', ['\u{1eb8}',
-        '\0', '\0']), ('\u{1ebb}', ['\u{1eba}', '\0', '\0']), ('\u{1ebd}', ['\u{1ebc}', '\0',
-        '\0']), ('\u{1ebf}', ['\u{1ebe}', '\0', '\0']), ('\u{1ec1}', ['\u{1ec0}', '\0', '\0']),
-        ('\u{1ec3}', ['\u{1ec2}', '\0', '\0']), ('\u{1ec5}', ['\u{1ec4}', '\0', '\0']), ('\u{1ec7}',
-        ['\u{1ec6}', '\0', '\0']), ('\u{1ec9}', ['\u{1ec8}', '\0', '\0']), ('\u{1ecb}', ['\u{1eca}',
-        '\0', '\0']), ('\u{1ecd}', ['\u{1ecc}', '\0', '\0']), ('\u{1ecf}', ['\u{1ece}', '\0',
-        '\0']), ('\u{1ed1}', ['\u{1ed0}', '\0', '\0']), ('\u{1ed3}', ['\u{1ed2}', '\0', '\0']),
-        ('\u{1ed5}', ['\u{1ed4}', '\0', '\0']), ('\u{1ed7}', ['\u{1ed6}', '\0', '\0']), ('\u{1ed9}',
-        ['\u{1ed8}', '\0', '\0']), ('\u{1edb}', ['\u{1eda}', '\0', '\0']), ('\u{1edd}', ['\u{1edc}',
-        '\0', '\0']), ('\u{1edf}', ['\u{1ede}', '\0', '\0']), ('\u{1ee1}', ['\u{1ee0}', '\0',
-        '\0']), ('\u{1ee3}', ['\u{1ee2}', '\0', '\0']), ('\u{1ee5}', ['\u{1ee4}', '\0', '\0']),
-        ('\u{1ee7}', ['\u{1ee6}', '\0', '\0']), ('\u{1ee9}', ['\u{1ee8}', '\0', '\0']), ('\u{1eeb}',
-        ['\u{1eea}', '\0', '\0']), ('\u{1eed}', ['\u{1eec}', '\0', '\0']), ('\u{1eef}', ['\u{1eee}',
-        '\0', '\0']), ('\u{1ef1}', ['\u{1ef0}', '\0', '\0']), ('\u{1ef3}', ['\u{1ef2}', '\0',
-        '\0']), ('\u{1ef5}', ['\u{1ef4}', '\0', '\0']), ('\u{1ef7}', ['\u{1ef6}', '\0', '\0']),
-        ('\u{1ef9}', ['\u{1ef8}', '\0', '\0']), ('\u{1efb}', ['\u{1efa}', '\0', '\0']), ('\u{1efd}',
-        ['\u{1efc}', '\0', '\0']), ('\u{1eff}', ['\u{1efe}', '\0', '\0']), ('\u{1f00}', ['\u{1f08}',
-        '\0', '\0']), ('\u{1f01}', ['\u{1f09}', '\0', '\0']), ('\u{1f02}', ['\u{1f0a}', '\0',
-        '\0']), ('\u{1f03}', ['\u{1f0b}', '\0', '\0']), ('\u{1f04}', ['\u{1f0c}', '\0', '\0']),
-        ('\u{1f05}', ['\u{1f0d}', '\0', '\0']), ('\u{1f06}', ['\u{1f0e}', '\0', '\0']), ('\u{1f07}',
-        ['\u{1f0f}', '\0', '\0']), ('\u{1f10}', ['\u{1f18}', '\0', '\0']), ('\u{1f11}', ['\u{1f19}',
-        '\0', '\0']), ('\u{1f12}', ['\u{1f1a}', '\0', '\0']), ('\u{1f13}', ['\u{1f1b}', '\0',
-        '\0']), ('\u{1f14}', ['\u{1f1c}', '\0', '\0']), ('\u{1f15}', ['\u{1f1d}', '\0', '\0']),
-        ('\u{1f20}', ['\u{1f28}', '\0', '\0']), ('\u{1f21}', ['\u{1f29}', '\0', '\0']), ('\u{1f22}',
-        ['\u{1f2a}', '\0', '\0']), ('\u{1f23}', ['\u{1f2b}', '\0', '\0']), ('\u{1f24}', ['\u{1f2c}',
-        '\0', '\0']), ('\u{1f25}', ['\u{1f2d}', '\0', '\0']), ('\u{1f26}', ['\u{1f2e}', '\0',
-        '\0']), ('\u{1f27}', ['\u{1f2f}', '\0', '\0']), ('\u{1f30}', ['\u{1f38}', '\0', '\0']),
-        ('\u{1f31}', ['\u{1f39}', '\0', '\0']), ('\u{1f32}', ['\u{1f3a}', '\0', '\0']), ('\u{1f33}',
-        ['\u{1f3b}', '\0', '\0']), ('\u{1f34}', ['\u{1f3c}', '\0', '\0']), ('\u{1f35}', ['\u{1f3d}',
-        '\0', '\0']), ('\u{1f36}', ['\u{1f3e}', '\0', '\0']), ('\u{1f37}', ['\u{1f3f}', '\0',
-        '\0']), ('\u{1f40}', ['\u{1f48}', '\0', '\0']), ('\u{1f41}', ['\u{1f49}', '\0', '\0']),
-        ('\u{1f42}', ['\u{1f4a}', '\0', '\0']), ('\u{1f43}', ['\u{1f4b}', '\0', '\0']), ('\u{1f44}',
-        ['\u{1f4c}', '\0', '\0']), ('\u{1f45}', ['\u{1f4d}', '\0', '\0']), ('\u{1f50}', ['\u{3a5}',
-        '\u{313}', '\0']), ('\u{1f51}', ['\u{1f59}', '\0', '\0']), ('\u{1f52}', ['\u{3a5}',
-        '\u{313}', '\u{300}']), ('\u{1f53}', ['\u{1f5b}', '\0', '\0']), ('\u{1f54}', ['\u{3a5}',
-        '\u{313}', '\u{301}']), ('\u{1f55}', ['\u{1f5d}', '\0', '\0']), ('\u{1f56}', ['\u{3a5}',
-        '\u{313}', '\u{342}']), ('\u{1f57}', ['\u{1f5f}', '\0', '\0']), ('\u{1f60}', ['\u{1f68}',
-        '\0', '\0']), ('\u{1f61}', ['\u{1f69}', '\0', '\0']), ('\u{1f62}', ['\u{1f6a}', '\0',
-        '\0']), ('\u{1f63}', ['\u{1f6b}', '\0', '\0']), ('\u{1f64}', ['\u{1f6c}', '\0', '\0']),
-        ('\u{1f65}', ['\u{1f6d}', '\0', '\0']), ('\u{1f66}', ['\u{1f6e}', '\0', '\0']), ('\u{1f67}',
-        ['\u{1f6f}', '\0', '\0']), ('\u{1f70}', ['\u{1fba}', '\0', '\0']), ('\u{1f71}', ['\u{1fbb}',
-        '\0', '\0']), ('\u{1f72}', ['\u{1fc8}', '\0', '\0']), ('\u{1f73}', ['\u{1fc9}', '\0',
-        '\0']), ('\u{1f74}', ['\u{1fca}', '\0', '\0']), ('\u{1f75}', ['\u{1fcb}', '\0', '\0']),
-        ('\u{1f76}', ['\u{1fda}', '\0', '\0']), ('\u{1f77}', ['\u{1fdb}', '\0', '\0']), ('\u{1f78}',
-        ['\u{1ff8}', '\0', '\0']), ('\u{1f79}', ['\u{1ff9}', '\0', '\0']), ('\u{1f7a}', ['\u{1fea}',
-        '\0', '\0']), ('\u{1f7b}', ['\u{1feb}', '\0', '\0']), ('\u{1f7c}', ['\u{1ffa}', '\0',
-        '\0']), ('\u{1f7d}', ['\u{1ffb}', '\0', '\0']), ('\u{1f80}', ['\u{1f08}', '\u{399}', '\0']),
-        ('\u{1f81}', ['\u{1f09}', '\u{399}', '\0']), ('\u{1f82}', ['\u{1f0a}', '\u{399}', '\0']),
-        ('\u{1f83}', ['\u{1f0b}', '\u{399}', '\0']), ('\u{1f84}', ['\u{1f0c}', '\u{399}', '\0']),
-        ('\u{1f85}', ['\u{1f0d}', '\u{399}', '\0']), ('\u{1f86}', ['\u{1f0e}', '\u{399}', '\0']),
-        ('\u{1f87}', ['\u{1f0f}', '\u{399}', '\0']), ('\u{1f88}', ['\u{1f08}', '\u{399}', '\0']),
-        ('\u{1f89}', ['\u{1f09}', '\u{399}', '\0']), ('\u{1f8a}', ['\u{1f0a}', '\u{399}', '\0']),
-        ('\u{1f8b}', ['\u{1f0b}', '\u{399}', '\0']), ('\u{1f8c}', ['\u{1f0c}', '\u{399}', '\0']),
-        ('\u{1f8d}', ['\u{1f0d}', '\u{399}', '\0']), ('\u{1f8e}', ['\u{1f0e}', '\u{399}', '\0']),
-        ('\u{1f8f}', ['\u{1f0f}', '\u{399}', '\0']), ('\u{1f90}', ['\u{1f28}', '\u{399}', '\0']),
-        ('\u{1f91}', ['\u{1f29}', '\u{399}', '\0']), ('\u{1f92}', ['\u{1f2a}', '\u{399}', '\0']),
-        ('\u{1f93}', ['\u{1f2b}', '\u{399}', '\0']), ('\u{1f94}', ['\u{1f2c}', '\u{399}', '\0']),
-        ('\u{1f95}', ['\u{1f2d}', '\u{399}', '\0']), ('\u{1f96}', ['\u{1f2e}', '\u{399}', '\0']),
-        ('\u{1f97}', ['\u{1f2f}', '\u{399}', '\0']), ('\u{1f98}', ['\u{1f28}', '\u{399}', '\0']),
-        ('\u{1f99}', ['\u{1f29}', '\u{399}', '\0']), ('\u{1f9a}', ['\u{1f2a}', '\u{399}', '\0']),
-        ('\u{1f9b}', ['\u{1f2b}', '\u{399}', '\0']), ('\u{1f9c}', ['\u{1f2c}', '\u{399}', '\0']),
-        ('\u{1f9d}', ['\u{1f2d}', '\u{399}', '\0']), ('\u{1f9e}', ['\u{1f2e}', '\u{399}', '\0']),
-        ('\u{1f9f}', ['\u{1f2f}', '\u{399}', '\0']), ('\u{1fa0}', ['\u{1f68}', '\u{399}', '\0']),
-        ('\u{1fa1}', ['\u{1f69}', '\u{399}', '\0']), ('\u{1fa2}', ['\u{1f6a}', '\u{399}', '\0']),
-        ('\u{1fa3}', ['\u{1f6b}', '\u{399}', '\0']), ('\u{1fa4}', ['\u{1f6c}', '\u{399}', '\0']),
-        ('\u{1fa5}', ['\u{1f6d}', '\u{399}', '\0']), ('\u{1fa6}', ['\u{1f6e}', '\u{399}', '\0']),
-        ('\u{1fa7}', ['\u{1f6f}', '\u{399}', '\0']), ('\u{1fa8}', ['\u{1f68}', '\u{399}', '\0']),
-        ('\u{1fa9}', ['\u{1f69}', '\u{399}', '\0']), ('\u{1faa}', ['\u{1f6a}', '\u{399}', '\0']),
-        ('\u{1fab}', ['\u{1f6b}', '\u{399}', '\0']), ('\u{1fac}', ['\u{1f6c}', '\u{399}', '\0']),
-        ('\u{1fad}', ['\u{1f6d}', '\u{399}', '\0']), ('\u{1fae}', ['\u{1f6e}', '\u{399}', '\0']),
-        ('\u{1faf}', ['\u{1f6f}', '\u{399}', '\0']), ('\u{1fb0}', ['\u{1fb8}', '\0', '\0']),
-        ('\u{1fb1}', ['\u{1fb9}', '\0', '\0']), ('\u{1fb2}', ['\u{1fba}', '\u{399}', '\0']),
-        ('\u{1fb3}', ['\u{391}', '\u{399}', '\0']), ('\u{1fb4}', ['\u{386}', '\u{399}', '\0']),
-        ('\u{1fb6}', ['\u{391}', '\u{342}', '\0']), ('\u{1fb7}', ['\u{391}', '\u{342}', '\u{399}']),
-        ('\u{1fbc}', ['\u{391}', '\u{399}', '\0']), ('\u{1fbe}', ['\u{399}', '\0', '\0']),
-        ('\u{1fc2}', ['\u{1fca}', '\u{399}', '\0']), ('\u{1fc3}', ['\u{397}', '\u{399}', '\0']),
-        ('\u{1fc4}', ['\u{389}', '\u{399}', '\0']), ('\u{1fc6}', ['\u{397}', '\u{342}', '\0']),
-        ('\u{1fc7}', ['\u{397}', '\u{342}', '\u{399}']), ('\u{1fcc}', ['\u{397}', '\u{399}', '\0']),
-        ('\u{1fd0}', ['\u{1fd8}', '\0', '\0']), ('\u{1fd1}', ['\u{1fd9}', '\0', '\0']), ('\u{1fd2}',
-        ['\u{399}', '\u{308}', '\u{300}']), ('\u{1fd3}', ['\u{399}', '\u{308}', '\u{301}']),
-        ('\u{1fd6}', ['\u{399}', '\u{342}', '\0']), ('\u{1fd7}', ['\u{399}', '\u{308}', '\u{342}']),
-        ('\u{1fe0}', ['\u{1fe8}', '\0', '\0']), ('\u{1fe1}', ['\u{1fe9}', '\0', '\0']), ('\u{1fe2}',
-        ['\u{3a5}', '\u{308}', '\u{300}']), ('\u{1fe3}', ['\u{3a5}', '\u{308}', '\u{301}']),
-        ('\u{1fe4}', ['\u{3a1}', '\u{313}', '\0']), ('\u{1fe5}', ['\u{1fec}', '\0', '\0']),
-        ('\u{1fe6}', ['\u{3a5}', '\u{342}', '\0']), ('\u{1fe7}', ['\u{3a5}', '\u{308}', '\u{342}']),
-        ('\u{1ff2}', ['\u{1ffa}', '\u{399}', '\0']), ('\u{1ff3}', ['\u{3a9}', '\u{399}', '\0']),
-        ('\u{1ff4}', ['\u{38f}', '\u{399}', '\0']), ('\u{1ff6}', ['\u{3a9}', '\u{342}', '\0']),
-        ('\u{1ff7}', ['\u{3a9}', '\u{342}', '\u{399}']), ('\u{1ffc}', ['\u{3a9}', '\u{399}', '\0']),
-        ('\u{214e}', ['\u{2132}', '\0', '\0']), ('\u{2170}', ['\u{2160}', '\0', '\0']), ('\u{2171}',
-        ['\u{2161}', '\0', '\0']), ('\u{2172}', ['\u{2162}', '\0', '\0']), ('\u{2173}', ['\u{2163}',
-        '\0', '\0']), ('\u{2174}', ['\u{2164}', '\0', '\0']), ('\u{2175}', ['\u{2165}', '\0',
-        '\0']), ('\u{2176}', ['\u{2166}', '\0', '\0']), ('\u{2177}', ['\u{2167}', '\0', '\0']),
-        ('\u{2178}', ['\u{2168}', '\0', '\0']), ('\u{2179}', ['\u{2169}', '\0', '\0']), ('\u{217a}',
-        ['\u{216a}', '\0', '\0']), ('\u{217b}', ['\u{216b}', '\0', '\0']), ('\u{217c}', ['\u{216c}',
-        '\0', '\0']), ('\u{217d}', ['\u{216d}', '\0', '\0']), ('\u{217e}', ['\u{216e}', '\0',
-        '\0']), ('\u{217f}', ['\u{216f}', '\0', '\0']), ('\u{2184}', ['\u{2183}', '\0', '\0']),
-        ('\u{24d0}', ['\u{24b6}', '\0', '\0']), ('\u{24d1}', ['\u{24b7}', '\0', '\0']), ('\u{24d2}',
-        ['\u{24b8}', '\0', '\0']), ('\u{24d3}', ['\u{24b9}', '\0', '\0']), ('\u{24d4}', ['\u{24ba}',
-        '\0', '\0']), ('\u{24d5}', ['\u{24bb}', '\0', '\0']), ('\u{24d6}', ['\u{24bc}', '\0',
-        '\0']), ('\u{24d7}', ['\u{24bd}', '\0', '\0']), ('\u{24d8}', ['\u{24be}', '\0', '\0']),
-        ('\u{24d9}', ['\u{24bf}', '\0', '\0']), ('\u{24da}', ['\u{24c0}', '\0', '\0']), ('\u{24db}',
-        ['\u{24c1}', '\0', '\0']), ('\u{24dc}', ['\u{24c2}', '\0', '\0']), ('\u{24dd}', ['\u{24c3}',
-        '\0', '\0']), ('\u{24de}', ['\u{24c4}', '\0', '\0']), ('\u{24df}', ['\u{24c5}', '\0',
-        '\0']), ('\u{24e0}', ['\u{24c6}', '\0', '\0']), ('\u{24e1}', ['\u{24c7}', '\0', '\0']),
-        ('\u{24e2}', ['\u{24c8}', '\0', '\0']), ('\u{24e3}', ['\u{24c9}', '\0', '\0']), ('\u{24e4}',
-        ['\u{24ca}', '\0', '\0']), ('\u{24e5}', ['\u{24cb}', '\0', '\0']), ('\u{24e6}', ['\u{24cc}',
-        '\0', '\0']), ('\u{24e7}', ['\u{24cd}', '\0', '\0']), ('\u{24e8}', ['\u{24ce}', '\0',
-        '\0']), ('\u{24e9}', ['\u{24cf}', '\0', '\0']), ('\u{2c30}', ['\u{2c00}', '\0', '\0']),
-        ('\u{2c31}', ['\u{2c01}', '\0', '\0']), ('\u{2c32}', ['\u{2c02}', '\0', '\0']), ('\u{2c33}',
-        ['\u{2c03}', '\0', '\0']), ('\u{2c34}', ['\u{2c04}', '\0', '\0']), ('\u{2c35}', ['\u{2c05}',
-        '\0', '\0']), ('\u{2c36}', ['\u{2c06}', '\0', '\0']), ('\u{2c37}', ['\u{2c07}', '\0',
-        '\0']), ('\u{2c38}', ['\u{2c08}', '\0', '\0']), ('\u{2c39}', ['\u{2c09}', '\0', '\0']),
-        ('\u{2c3a}', ['\u{2c0a}', '\0', '\0']), ('\u{2c3b}', ['\u{2c0b}', '\0', '\0']), ('\u{2c3c}',
-        ['\u{2c0c}', '\0', '\0']), ('\u{2c3d}', ['\u{2c0d}', '\0', '\0']), ('\u{2c3e}', ['\u{2c0e}',
-        '\0', '\0']), ('\u{2c3f}', ['\u{2c0f}', '\0', '\0']), ('\u{2c40}', ['\u{2c10}', '\0',
-        '\0']), ('\u{2c41}', ['\u{2c11}', '\0', '\0']), ('\u{2c42}', ['\u{2c12}', '\0', '\0']),
-        ('\u{2c43}', ['\u{2c13}', '\0', '\0']), ('\u{2c44}', ['\u{2c14}', '\0', '\0']), ('\u{2c45}',
-        ['\u{2c15}', '\0', '\0']), ('\u{2c46}', ['\u{2c16}', '\0', '\0']), ('\u{2c47}', ['\u{2c17}',
-        '\0', '\0']), ('\u{2c48}', ['\u{2c18}', '\0', '\0']), ('\u{2c49}', ['\u{2c19}', '\0',
-        '\0']), ('\u{2c4a}', ['\u{2c1a}', '\0', '\0']), ('\u{2c4b}', ['\u{2c1b}', '\0', '\0']),
-        ('\u{2c4c}', ['\u{2c1c}', '\0', '\0']), ('\u{2c4d}', ['\u{2c1d}', '\0', '\0']), ('\u{2c4e}',
-        ['\u{2c1e}', '\0', '\0']), ('\u{2c4f}', ['\u{2c1f}', '\0', '\0']), ('\u{2c50}', ['\u{2c20}',
-        '\0', '\0']), ('\u{2c51}', ['\u{2c21}', '\0', '\0']), ('\u{2c52}', ['\u{2c22}', '\0',
-        '\0']), ('\u{2c53}', ['\u{2c23}', '\0', '\0']), ('\u{2c54}', ['\u{2c24}', '\0', '\0']),
-        ('\u{2c55}', ['\u{2c25}', '\0', '\0']), ('\u{2c56}', ['\u{2c26}', '\0', '\0']), ('\u{2c57}',
-        ['\u{2c27}', '\0', '\0']), ('\u{2c58}', ['\u{2c28}', '\0', '\0']), ('\u{2c59}', ['\u{2c29}',
-        '\0', '\0']), ('\u{2c5a}', ['\u{2c2a}', '\0', '\0']), ('\u{2c5b}', ['\u{2c2b}', '\0',
-        '\0']), ('\u{2c5c}', ['\u{2c2c}', '\0', '\0']), ('\u{2c5d}', ['\u{2c2d}', '\0', '\0']),
-        ('\u{2c5e}', ['\u{2c2e}', '\0', '\0']), ('\u{2c61}', ['\u{2c60}', '\0', '\0']), ('\u{2c65}',
-        ['\u{23a}', '\0', '\0']), ('\u{2c66}', ['\u{23e}', '\0', '\0']), ('\u{2c68}', ['\u{2c67}',
-        '\0', '\0']), ('\u{2c6a}', ['\u{2c69}', '\0', '\0']), ('\u{2c6c}', ['\u{2c6b}', '\0',
-        '\0']), ('\u{2c73}', ['\u{2c72}', '\0', '\0']), ('\u{2c76}', ['\u{2c75}', '\0', '\0']),
-        ('\u{2c81}', ['\u{2c80}', '\0', '\0']), ('\u{2c83}', ['\u{2c82}', '\0', '\0']), ('\u{2c85}',
-        ['\u{2c84}', '\0', '\0']), ('\u{2c87}', ['\u{2c86}', '\0', '\0']), ('\u{2c89}', ['\u{2c88}',
-        '\0', '\0']), ('\u{2c8b}', ['\u{2c8a}', '\0', '\0']), ('\u{2c8d}', ['\u{2c8c}', '\0',
-        '\0']), ('\u{2c8f}', ['\u{2c8e}', '\0', '\0']), ('\u{2c91}', ['\u{2c90}', '\0', '\0']),
-        ('\u{2c93}', ['\u{2c92}', '\0', '\0']), ('\u{2c95}', ['\u{2c94}', '\0', '\0']), ('\u{2c97}',
-        ['\u{2c96}', '\0', '\0']), ('\u{2c99}', ['\u{2c98}', '\0', '\0']), ('\u{2c9b}', ['\u{2c9a}',
-        '\0', '\0']), ('\u{2c9d}', ['\u{2c9c}', '\0', '\0']), ('\u{2c9f}', ['\u{2c9e}', '\0',
-        '\0']), ('\u{2ca1}', ['\u{2ca0}', '\0', '\0']), ('\u{2ca3}', ['\u{2ca2}', '\0', '\0']),
-        ('\u{2ca5}', ['\u{2ca4}', '\0', '\0']), ('\u{2ca7}', ['\u{2ca6}', '\0', '\0']), ('\u{2ca9}',
-        ['\u{2ca8}', '\0', '\0']), ('\u{2cab}', ['\u{2caa}', '\0', '\0']), ('\u{2cad}', ['\u{2cac}',
-        '\0', '\0']), ('\u{2caf}', ['\u{2cae}', '\0', '\0']), ('\u{2cb1}', ['\u{2cb0}', '\0',
-        '\0']), ('\u{2cb3}', ['\u{2cb2}', '\0', '\0']), ('\u{2cb5}', ['\u{2cb4}', '\0', '\0']),
-        ('\u{2cb7}', ['\u{2cb6}', '\0', '\0']), ('\u{2cb9}', ['\u{2cb8}', '\0', '\0']), ('\u{2cbb}',
-        ['\u{2cba}', '\0', '\0']), ('\u{2cbd}', ['\u{2cbc}', '\0', '\0']), ('\u{2cbf}', ['\u{2cbe}',
-        '\0', '\0']), ('\u{2cc1}', ['\u{2cc0}', '\0', '\0']), ('\u{2cc3}', ['\u{2cc2}', '\0',
-        '\0']), ('\u{2cc5}', ['\u{2cc4}', '\0', '\0']), ('\u{2cc7}', ['\u{2cc6}', '\0', '\0']),
-        ('\u{2cc9}', ['\u{2cc8}', '\0', '\0']), ('\u{2ccb}', ['\u{2cca}', '\0', '\0']), ('\u{2ccd}',
-        ['\u{2ccc}', '\0', '\0']), ('\u{2ccf}', ['\u{2cce}', '\0', '\0']), ('\u{2cd1}', ['\u{2cd0}',
-        '\0', '\0']), ('\u{2cd3}', ['\u{2cd2}', '\0', '\0']), ('\u{2cd5}', ['\u{2cd4}', '\0',
-        '\0']), ('\u{2cd7}', ['\u{2cd6}', '\0', '\0']), ('\u{2cd9}', ['\u{2cd8}', '\0', '\0']),
-        ('\u{2cdb}', ['\u{2cda}', '\0', '\0']), ('\u{2cdd}', ['\u{2cdc}', '\0', '\0']), ('\u{2cdf}',
-        ['\u{2cde}', '\0', '\0']), ('\u{2ce1}', ['\u{2ce0}', '\0', '\0']), ('\u{2ce3}', ['\u{2ce2}',
-        '\0', '\0']), ('\u{2cec}', ['\u{2ceb}', '\0', '\0']), ('\u{2cee}', ['\u{2ced}', '\0',
-        '\0']), ('\u{2cf3}', ['\u{2cf2}', '\0', '\0']), ('\u{2d00}', ['\u{10a0}', '\0', '\0']),
-        ('\u{2d01}', ['\u{10a1}', '\0', '\0']), ('\u{2d02}', ['\u{10a2}', '\0', '\0']), ('\u{2d03}',
-        ['\u{10a3}', '\0', '\0']), ('\u{2d04}', ['\u{10a4}', '\0', '\0']), ('\u{2d05}', ['\u{10a5}',
-        '\0', '\0']), ('\u{2d06}', ['\u{10a6}', '\0', '\0']), ('\u{2d07}', ['\u{10a7}', '\0',
-        '\0']), ('\u{2d08}', ['\u{10a8}', '\0', '\0']), ('\u{2d09}', ['\u{10a9}', '\0', '\0']),
-        ('\u{2d0a}', ['\u{10aa}', '\0', '\0']), ('\u{2d0b}', ['\u{10ab}', '\0', '\0']), ('\u{2d0c}',
-        ['\u{10ac}', '\0', '\0']), ('\u{2d0d}', ['\u{10ad}', '\0', '\0']), ('\u{2d0e}', ['\u{10ae}',
-        '\0', '\0']), ('\u{2d0f}', ['\u{10af}', '\0', '\0']), ('\u{2d10}', ['\u{10b0}', '\0',
-        '\0']), ('\u{2d11}', ['\u{10b1}', '\0', '\0']), ('\u{2d12}', ['\u{10b2}', '\0', '\0']),
-        ('\u{2d13}', ['\u{10b3}', '\0', '\0']), ('\u{2d14}', ['\u{10b4}', '\0', '\0']), ('\u{2d15}',
-        ['\u{10b5}', '\0', '\0']), ('\u{2d16}', ['\u{10b6}', '\0', '\0']), ('\u{2d17}', ['\u{10b7}',
-        '\0', '\0']), ('\u{2d18}', ['\u{10b8}', '\0', '\0']), ('\u{2d19}', ['\u{10b9}', '\0',
-        '\0']), ('\u{2d1a}', ['\u{10ba}', '\0', '\0']), ('\u{2d1b}', ['\u{10bb}', '\0', '\0']),
-        ('\u{2d1c}', ['\u{10bc}', '\0', '\0']), ('\u{2d1d}', ['\u{10bd}', '\0', '\0']), ('\u{2d1e}',
-        ['\u{10be}', '\0', '\0']), ('\u{2d1f}', ['\u{10bf}', '\0', '\0']), ('\u{2d20}', ['\u{10c0}',
-        '\0', '\0']), ('\u{2d21}', ['\u{10c1}', '\0', '\0']), ('\u{2d22}', ['\u{10c2}', '\0',
-        '\0']), ('\u{2d23}', ['\u{10c3}', '\0', '\0']), ('\u{2d24}', ['\u{10c4}', '\0', '\0']),
-        ('\u{2d25}', ['\u{10c5}', '\0', '\0']), ('\u{2d27}', ['\u{10c7}', '\0', '\0']), ('\u{2d2d}',
-        ['\u{10cd}', '\0', '\0']), ('\u{a641}', ['\u{a640}', '\0', '\0']), ('\u{a643}', ['\u{a642}',
-        '\0', '\0']), ('\u{a645}', ['\u{a644}', '\0', '\0']), ('\u{a647}', ['\u{a646}', '\0',
-        '\0']), ('\u{a649}', ['\u{a648}', '\0', '\0']), ('\u{a64b}', ['\u{a64a}', '\0', '\0']),
-        ('\u{a64d}', ['\u{a64c}', '\0', '\0']), ('\u{a64f}', ['\u{a64e}', '\0', '\0']), ('\u{a651}',
-        ['\u{a650}', '\0', '\0']), ('\u{a653}', ['\u{a652}', '\0', '\0']), ('\u{a655}', ['\u{a654}',
-        '\0', '\0']), ('\u{a657}', ['\u{a656}', '\0', '\0']), ('\u{a659}', ['\u{a658}', '\0',
-        '\0']), ('\u{a65b}', ['\u{a65a}', '\0', '\0']), ('\u{a65d}', ['\u{a65c}', '\0', '\0']),
-        ('\u{a65f}', ['\u{a65e}', '\0', '\0']), ('\u{a661}', ['\u{a660}', '\0', '\0']), ('\u{a663}',
-        ['\u{a662}', '\0', '\0']), ('\u{a665}', ['\u{a664}', '\0', '\0']), ('\u{a667}', ['\u{a666}',
-        '\0', '\0']), ('\u{a669}', ['\u{a668}', '\0', '\0']), ('\u{a66b}', ['\u{a66a}', '\0',
-        '\0']), ('\u{a66d}', ['\u{a66c}', '\0', '\0']), ('\u{a681}', ['\u{a680}', '\0', '\0']),
-        ('\u{a683}', ['\u{a682}', '\0', '\0']), ('\u{a685}', ['\u{a684}', '\0', '\0']), ('\u{a687}',
-        ['\u{a686}', '\0', '\0']), ('\u{a689}', ['\u{a688}', '\0', '\0']), ('\u{a68b}', ['\u{a68a}',
-        '\0', '\0']), ('\u{a68d}', ['\u{a68c}', '\0', '\0']), ('\u{a68f}', ['\u{a68e}', '\0',
-        '\0']), ('\u{a691}', ['\u{a690}', '\0', '\0']), ('\u{a693}', ['\u{a692}', '\0', '\0']),
-        ('\u{a695}', ['\u{a694}', '\0', '\0']), ('\u{a697}', ['\u{a696}', '\0', '\0']), ('\u{a699}',
-        ['\u{a698}', '\0', '\0']), ('\u{a69b}', ['\u{a69a}', '\0', '\0']), ('\u{a723}', ['\u{a722}',
-        '\0', '\0']), ('\u{a725}', ['\u{a724}', '\0', '\0']), ('\u{a727}', ['\u{a726}', '\0',
-        '\0']), ('\u{a729}', ['\u{a728}', '\0', '\0']), ('\u{a72b}', ['\u{a72a}', '\0', '\0']),
-        ('\u{a72d}', ['\u{a72c}', '\0', '\0']), ('\u{a72f}', ['\u{a72e}', '\0', '\0']), ('\u{a733}',
-        ['\u{a732}', '\0', '\0']), ('\u{a735}', ['\u{a734}', '\0', '\0']), ('\u{a737}', ['\u{a736}',
-        '\0', '\0']), ('\u{a739}', ['\u{a738}', '\0', '\0']), ('\u{a73b}', ['\u{a73a}', '\0',
-        '\0']), ('\u{a73d}', ['\u{a73c}', '\0', '\0']), ('\u{a73f}', ['\u{a73e}', '\0', '\0']),
-        ('\u{a741}', ['\u{a740}', '\0', '\0']), ('\u{a743}', ['\u{a742}', '\0', '\0']), ('\u{a745}',
-        ['\u{a744}', '\0', '\0']), ('\u{a747}', ['\u{a746}', '\0', '\0']), ('\u{a749}', ['\u{a748}',
-        '\0', '\0']), ('\u{a74b}', ['\u{a74a}', '\0', '\0']), ('\u{a74d}', ['\u{a74c}', '\0',
-        '\0']), ('\u{a74f}', ['\u{a74e}', '\0', '\0']), ('\u{a751}', ['\u{a750}', '\0', '\0']),
-        ('\u{a753}', ['\u{a752}', '\0', '\0']), ('\u{a755}', ['\u{a754}', '\0', '\0']), ('\u{a757}',
-        ['\u{a756}', '\0', '\0']), ('\u{a759}', ['\u{a758}', '\0', '\0']), ('\u{a75b}', ['\u{a75a}',
-        '\0', '\0']), ('\u{a75d}', ['\u{a75c}', '\0', '\0']), ('\u{a75f}', ['\u{a75e}', '\0',
-        '\0']), ('\u{a761}', ['\u{a760}', '\0', '\0']), ('\u{a763}', ['\u{a762}', '\0', '\0']),
-        ('\u{a765}', ['\u{a764}', '\0', '\0']), ('\u{a767}', ['\u{a766}', '\0', '\0']), ('\u{a769}',
-        ['\u{a768}', '\0', '\0']), ('\u{a76b}', ['\u{a76a}', '\0', '\0']), ('\u{a76d}', ['\u{a76c}',
-        '\0', '\0']), ('\u{a76f}', ['\u{a76e}', '\0', '\0']), ('\u{a77a}', ['\u{a779}', '\0',
-        '\0']), ('\u{a77c}', ['\u{a77b}', '\0', '\0']), ('\u{a77f}', ['\u{a77e}', '\0', '\0']),
-        ('\u{a781}', ['\u{a780}', '\0', '\0']), ('\u{a783}', ['\u{a782}', '\0', '\0']), ('\u{a785}',
-        ['\u{a784}', '\0', '\0']), ('\u{a787}', ['\u{a786}', '\0', '\0']), ('\u{a78c}', ['\u{a78b}',
-        '\0', '\0']), ('\u{a791}', ['\u{a790}', '\0', '\0']), ('\u{a793}', ['\u{a792}', '\0',
-        '\0']), ('\u{a794}', ['\u{a7c4}', '\0', '\0']), ('\u{a797}', ['\u{a796}', '\0', '\0']),
-        ('\u{a799}', ['\u{a798}', '\0', '\0']), ('\u{a79b}', ['\u{a79a}', '\0', '\0']), ('\u{a79d}',
-        ['\u{a79c}', '\0', '\0']), ('\u{a79f}', ['\u{a79e}', '\0', '\0']), ('\u{a7a1}', ['\u{a7a0}',
-        '\0', '\0']), ('\u{a7a3}', ['\u{a7a2}', '\0', '\0']), ('\u{a7a5}', ['\u{a7a4}', '\0',
-        '\0']), ('\u{a7a7}', ['\u{a7a6}', '\0', '\0']), ('\u{a7a9}', ['\u{a7a8}', '\0', '\0']),
-        ('\u{a7b5}', ['\u{a7b4}', '\0', '\0']), ('\u{a7b7}', ['\u{a7b6}', '\0', '\0']), ('\u{a7b9}',
-        ['\u{a7b8}', '\0', '\0']), ('\u{a7bb}', ['\u{a7ba}', '\0', '\0']), ('\u{a7bd}', ['\u{a7bc}',
-        '\0', '\0']), ('\u{a7bf}', ['\u{a7be}', '\0', '\0']), ('\u{a7c3}', ['\u{a7c2}', '\0',
-        '\0']), ('\u{ab53}', ['\u{a7b3}', '\0', '\0']), ('\u{ab70}', ['\u{13a0}', '\0', '\0']),
-        ('\u{ab71}', ['\u{13a1}', '\0', '\0']), ('\u{ab72}', ['\u{13a2}', '\0', '\0']), ('\u{ab73}',
-        ['\u{13a3}', '\0', '\0']), ('\u{ab74}', ['\u{13a4}', '\0', '\0']), ('\u{ab75}', ['\u{13a5}',
-        '\0', '\0']), ('\u{ab76}', ['\u{13a6}', '\0', '\0']), ('\u{ab77}', ['\u{13a7}', '\0',
-        '\0']), ('\u{ab78}', ['\u{13a8}', '\0', '\0']), ('\u{ab79}', ['\u{13a9}', '\0', '\0']),
-        ('\u{ab7a}', ['\u{13aa}', '\0', '\0']), ('\u{ab7b}', ['\u{13ab}', '\0', '\0']), ('\u{ab7c}',
-        ['\u{13ac}', '\0', '\0']), ('\u{ab7d}', ['\u{13ad}', '\0', '\0']), ('\u{ab7e}', ['\u{13ae}',
-        '\0', '\0']), ('\u{ab7f}', ['\u{13af}', '\0', '\0']), ('\u{ab80}', ['\u{13b0}', '\0',
-        '\0']), ('\u{ab81}', ['\u{13b1}', '\0', '\0']), ('\u{ab82}', ['\u{13b2}', '\0', '\0']),
-        ('\u{ab83}', ['\u{13b3}', '\0', '\0']), ('\u{ab84}', ['\u{13b4}', '\0', '\0']), ('\u{ab85}',
-        ['\u{13b5}', '\0', '\0']), ('\u{ab86}', ['\u{13b6}', '\0', '\0']), ('\u{ab87}', ['\u{13b7}',
-        '\0', '\0']), ('\u{ab88}', ['\u{13b8}', '\0', '\0']), ('\u{ab89}', ['\u{13b9}', '\0',
-        '\0']), ('\u{ab8a}', ['\u{13ba}', '\0', '\0']), ('\u{ab8b}', ['\u{13bb}', '\0', '\0']),
-        ('\u{ab8c}', ['\u{13bc}', '\0', '\0']), ('\u{ab8d}', ['\u{13bd}', '\0', '\0']), ('\u{ab8e}',
-        ['\u{13be}', '\0', '\0']), ('\u{ab8f}', ['\u{13bf}', '\0', '\0']), ('\u{ab90}', ['\u{13c0}',
-        '\0', '\0']), ('\u{ab91}', ['\u{13c1}', '\0', '\0']), ('\u{ab92}', ['\u{13c2}', '\0',
-        '\0']), ('\u{ab93}', ['\u{13c3}', '\0', '\0']), ('\u{ab94}', ['\u{13c4}', '\0', '\0']),
-        ('\u{ab95}', ['\u{13c5}', '\0', '\0']), ('\u{ab96}', ['\u{13c6}', '\0', '\0']), ('\u{ab97}',
-        ['\u{13c7}', '\0', '\0']), ('\u{ab98}', ['\u{13c8}', '\0', '\0']), ('\u{ab99}', ['\u{13c9}',
-        '\0', '\0']), ('\u{ab9a}', ['\u{13ca}', '\0', '\0']), ('\u{ab9b}', ['\u{13cb}', '\0',
-        '\0']), ('\u{ab9c}', ['\u{13cc}', '\0', '\0']), ('\u{ab9d}', ['\u{13cd}', '\0', '\0']),
-        ('\u{ab9e}', ['\u{13ce}', '\0', '\0']), ('\u{ab9f}', ['\u{13cf}', '\0', '\0']), ('\u{aba0}',
-        ['\u{13d0}', '\0', '\0']), ('\u{aba1}', ['\u{13d1}', '\0', '\0']), ('\u{aba2}', ['\u{13d2}',
-        '\0', '\0']), ('\u{aba3}', ['\u{13d3}', '\0', '\0']), ('\u{aba4}', ['\u{13d4}', '\0',
-        '\0']), ('\u{aba5}', ['\u{13d5}', '\0', '\0']), ('\u{aba6}', ['\u{13d6}', '\0', '\0']),
-        ('\u{aba7}', ['\u{13d7}', '\0', '\0']), ('\u{aba8}', ['\u{13d8}', '\0', '\0']), ('\u{aba9}',
-        ['\u{13d9}', '\0', '\0']), ('\u{abaa}', ['\u{13da}', '\0', '\0']), ('\u{abab}', ['\u{13db}',
-        '\0', '\0']), ('\u{abac}', ['\u{13dc}', '\0', '\0']), ('\u{abad}', ['\u{13dd}', '\0',
-        '\0']), ('\u{abae}', ['\u{13de}', '\0', '\0']), ('\u{abaf}', ['\u{13df}', '\0', '\0']),
-        ('\u{abb0}', ['\u{13e0}', '\0', '\0']), ('\u{abb1}', ['\u{13e1}', '\0', '\0']), ('\u{abb2}',
-        ['\u{13e2}', '\0', '\0']), ('\u{abb3}', ['\u{13e3}', '\0', '\0']), ('\u{abb4}', ['\u{13e4}',
-        '\0', '\0']), ('\u{abb5}', ['\u{13e5}', '\0', '\0']), ('\u{abb6}', ['\u{13e6}', '\0',
-        '\0']), ('\u{abb7}', ['\u{13e7}', '\0', '\0']), ('\u{abb8}', ['\u{13e8}', '\0', '\0']),
-        ('\u{abb9}', ['\u{13e9}', '\0', '\0']), ('\u{abba}', ['\u{13ea}', '\0', '\0']), ('\u{abbb}',
-        ['\u{13eb}', '\0', '\0']), ('\u{abbc}', ['\u{13ec}', '\0', '\0']), ('\u{abbd}', ['\u{13ed}',
-        '\0', '\0']), ('\u{abbe}', ['\u{13ee}', '\0', '\0']), ('\u{abbf}', ['\u{13ef}', '\0',
-        '\0']), ('\u{fb00}', ['\u{46}', '\u{46}', '\0']), ('\u{fb01}', ['\u{46}', '\u{49}', '\0']),
-        ('\u{fb02}', ['\u{46}', '\u{4c}', '\0']), ('\u{fb03}', ['\u{46}', '\u{46}', '\u{49}']),
-        ('\u{fb04}', ['\u{46}', '\u{46}', '\u{4c}']), ('\u{fb05}', ['\u{53}', '\u{54}', '\0']),
-        ('\u{fb06}', ['\u{53}', '\u{54}', '\0']), ('\u{fb13}', ['\u{544}', '\u{546}', '\0']),
-        ('\u{fb14}', ['\u{544}', '\u{535}', '\0']), ('\u{fb15}', ['\u{544}', '\u{53b}', '\0']),
-        ('\u{fb16}', ['\u{54e}', '\u{546}', '\0']), ('\u{fb17}', ['\u{544}', '\u{53d}', '\0']),
-        ('\u{ff41}', ['\u{ff21}', '\0', '\0']), ('\u{ff42}', ['\u{ff22}', '\0', '\0']), ('\u{ff43}',
-        ['\u{ff23}', '\0', '\0']), ('\u{ff44}', ['\u{ff24}', '\0', '\0']), ('\u{ff45}', ['\u{ff25}',
-        '\0', '\0']), ('\u{ff46}', ['\u{ff26}', '\0', '\0']), ('\u{ff47}', ['\u{ff27}', '\0',
-        '\0']), ('\u{ff48}', ['\u{ff28}', '\0', '\0']), ('\u{ff49}', ['\u{ff29}', '\0', '\0']),
-        ('\u{ff4a}', ['\u{ff2a}', '\0', '\0']), ('\u{ff4b}', ['\u{ff2b}', '\0', '\0']), ('\u{ff4c}',
-        ['\u{ff2c}', '\0', '\0']), ('\u{ff4d}', ['\u{ff2d}', '\0', '\0']), ('\u{ff4e}', ['\u{ff2e}',
-        '\0', '\0']), ('\u{ff4f}', ['\u{ff2f}', '\0', '\0']), ('\u{ff50}', ['\u{ff30}', '\0',
-        '\0']), ('\u{ff51}', ['\u{ff31}', '\0', '\0']), ('\u{ff52}', ['\u{ff32}', '\0', '\0']),
-        ('\u{ff53}', ['\u{ff33}', '\0', '\0']), ('\u{ff54}', ['\u{ff34}', '\0', '\0']), ('\u{ff55}',
-        ['\u{ff35}', '\0', '\0']), ('\u{ff56}', ['\u{ff36}', '\0', '\0']), ('\u{ff57}', ['\u{ff37}',
-        '\0', '\0']), ('\u{ff58}', ['\u{ff38}', '\0', '\0']), ('\u{ff59}', ['\u{ff39}', '\0',
-        '\0']), ('\u{ff5a}', ['\u{ff3a}', '\0', '\0']), ('\u{10428}', ['\u{10400}', '\0', '\0']),
-        ('\u{10429}', ['\u{10401}', '\0', '\0']), ('\u{1042a}', ['\u{10402}', '\0', '\0']),
-        ('\u{1042b}', ['\u{10403}', '\0', '\0']), ('\u{1042c}', ['\u{10404}', '\0', '\0']),
-        ('\u{1042d}', ['\u{10405}', '\0', '\0']), ('\u{1042e}', ['\u{10406}', '\0', '\0']),
-        ('\u{1042f}', ['\u{10407}', '\0', '\0']), ('\u{10430}', ['\u{10408}', '\0', '\0']),
-        ('\u{10431}', ['\u{10409}', '\0', '\0']), ('\u{10432}', ['\u{1040a}', '\0', '\0']),
-        ('\u{10433}', ['\u{1040b}', '\0', '\0']), ('\u{10434}', ['\u{1040c}', '\0', '\0']),
-        ('\u{10435}', ['\u{1040d}', '\0', '\0']), ('\u{10436}', ['\u{1040e}', '\0', '\0']),
-        ('\u{10437}', ['\u{1040f}', '\0', '\0']), ('\u{10438}', ['\u{10410}', '\0', '\0']),
-        ('\u{10439}', ['\u{10411}', '\0', '\0']), ('\u{1043a}', ['\u{10412}', '\0', '\0']),
-        ('\u{1043b}', ['\u{10413}', '\0', '\0']), ('\u{1043c}', ['\u{10414}', '\0', '\0']),
-        ('\u{1043d}', ['\u{10415}', '\0', '\0']), ('\u{1043e}', ['\u{10416}', '\0', '\0']),
-        ('\u{1043f}', ['\u{10417}', '\0', '\0']), ('\u{10440}', ['\u{10418}', '\0', '\0']),
-        ('\u{10441}', ['\u{10419}', '\0', '\0']), ('\u{10442}', ['\u{1041a}', '\0', '\0']),
-        ('\u{10443}', ['\u{1041b}', '\0', '\0']), ('\u{10444}', ['\u{1041c}', '\0', '\0']),
-        ('\u{10445}', ['\u{1041d}', '\0', '\0']), ('\u{10446}', ['\u{1041e}', '\0', '\0']),
-        ('\u{10447}', ['\u{1041f}', '\0', '\0']), ('\u{10448}', ['\u{10420}', '\0', '\0']),
-        ('\u{10449}', ['\u{10421}', '\0', '\0']), ('\u{1044a}', ['\u{10422}', '\0', '\0']),
-        ('\u{1044b}', ['\u{10423}', '\0', '\0']), ('\u{1044c}', ['\u{10424}', '\0', '\0']),
-        ('\u{1044d}', ['\u{10425}', '\0', '\0']), ('\u{1044e}', ['\u{10426}', '\0', '\0']),
-        ('\u{1044f}', ['\u{10427}', '\0', '\0']), ('\u{104d8}', ['\u{104b0}', '\0', '\0']),
-        ('\u{104d9}', ['\u{104b1}', '\0', '\0']), ('\u{104da}', ['\u{104b2}', '\0', '\0']),
-        ('\u{104db}', ['\u{104b3}', '\0', '\0']), ('\u{104dc}', ['\u{104b4}', '\0', '\0']),
-        ('\u{104dd}', ['\u{104b5}', '\0', '\0']), ('\u{104de}', ['\u{104b6}', '\0', '\0']),
-        ('\u{104df}', ['\u{104b7}', '\0', '\0']), ('\u{104e0}', ['\u{104b8}', '\0', '\0']),
-        ('\u{104e1}', ['\u{104b9}', '\0', '\0']), ('\u{104e2}', ['\u{104ba}', '\0', '\0']),
-        ('\u{104e3}', ['\u{104bb}', '\0', '\0']), ('\u{104e4}', ['\u{104bc}', '\0', '\0']),
-        ('\u{104e5}', ['\u{104bd}', '\0', '\0']), ('\u{104e6}', ['\u{104be}', '\0', '\0']),
-        ('\u{104e7}', ['\u{104bf}', '\0', '\0']), ('\u{104e8}', ['\u{104c0}', '\0', '\0']),
-        ('\u{104e9}', ['\u{104c1}', '\0', '\0']), ('\u{104ea}', ['\u{104c2}', '\0', '\0']),
-        ('\u{104eb}', ['\u{104c3}', '\0', '\0']), ('\u{104ec}', ['\u{104c4}', '\0', '\0']),
-        ('\u{104ed}', ['\u{104c5}', '\0', '\0']), ('\u{104ee}', ['\u{104c6}', '\0', '\0']),
-        ('\u{104ef}', ['\u{104c7}', '\0', '\0']), ('\u{104f0}', ['\u{104c8}', '\0', '\0']),
-        ('\u{104f1}', ['\u{104c9}', '\0', '\0']), ('\u{104f2}', ['\u{104ca}', '\0', '\0']),
-        ('\u{104f3}', ['\u{104cb}', '\0', '\0']), ('\u{104f4}', ['\u{104cc}', '\0', '\0']),
-        ('\u{104f5}', ['\u{104cd}', '\0', '\0']), ('\u{104f6}', ['\u{104ce}', '\0', '\0']),
-        ('\u{104f7}', ['\u{104cf}', '\0', '\0']), ('\u{104f8}', ['\u{104d0}', '\0', '\0']),
-        ('\u{104f9}', ['\u{104d1}', '\0', '\0']), ('\u{104fa}', ['\u{104d2}', '\0', '\0']),
-        ('\u{104fb}', ['\u{104d3}', '\0', '\0']), ('\u{10cc0}', ['\u{10c80}', '\0', '\0']),
-        ('\u{10cc1}', ['\u{10c81}', '\0', '\0']), ('\u{10cc2}', ['\u{10c82}', '\0', '\0']),
-        ('\u{10cc3}', ['\u{10c83}', '\0', '\0']), ('\u{10cc4}', ['\u{10c84}', '\0', '\0']),
-        ('\u{10cc5}', ['\u{10c85}', '\0', '\0']), ('\u{10cc6}', ['\u{10c86}', '\0', '\0']),
-        ('\u{10cc7}', ['\u{10c87}', '\0', '\0']), ('\u{10cc8}', ['\u{10c88}', '\0', '\0']),
-        ('\u{10cc9}', ['\u{10c89}', '\0', '\0']), ('\u{10cca}', ['\u{10c8a}', '\0', '\0']),
-        ('\u{10ccb}', ['\u{10c8b}', '\0', '\0']), ('\u{10ccc}', ['\u{10c8c}', '\0', '\0']),
-        ('\u{10ccd}', ['\u{10c8d}', '\0', '\0']), ('\u{10cce}', ['\u{10c8e}', '\0', '\0']),
-        ('\u{10ccf}', ['\u{10c8f}', '\0', '\0']), ('\u{10cd0}', ['\u{10c90}', '\0', '\0']),
-        ('\u{10cd1}', ['\u{10c91}', '\0', '\0']), ('\u{10cd2}', ['\u{10c92}', '\0', '\0']),
-        ('\u{10cd3}', ['\u{10c93}', '\0', '\0']), ('\u{10cd4}', ['\u{10c94}', '\0', '\0']),
-        ('\u{10cd5}', ['\u{10c95}', '\0', '\0']), ('\u{10cd6}', ['\u{10c96}', '\0', '\0']),
-        ('\u{10cd7}', ['\u{10c97}', '\0', '\0']), ('\u{10cd8}', ['\u{10c98}', '\0', '\0']),
-        ('\u{10cd9}', ['\u{10c99}', '\0', '\0']), ('\u{10cda}', ['\u{10c9a}', '\0', '\0']),
-        ('\u{10cdb}', ['\u{10c9b}', '\0', '\0']), ('\u{10cdc}', ['\u{10c9c}', '\0', '\0']),
-        ('\u{10cdd}', ['\u{10c9d}', '\0', '\0']), ('\u{10cde}', ['\u{10c9e}', '\0', '\0']),
-        ('\u{10cdf}', ['\u{10c9f}', '\0', '\0']), ('\u{10ce0}', ['\u{10ca0}', '\0', '\0']),
-        ('\u{10ce1}', ['\u{10ca1}', '\0', '\0']), ('\u{10ce2}', ['\u{10ca2}', '\0', '\0']),
-        ('\u{10ce3}', ['\u{10ca3}', '\0', '\0']), ('\u{10ce4}', ['\u{10ca4}', '\0', '\0']),
-        ('\u{10ce5}', ['\u{10ca5}', '\0', '\0']), ('\u{10ce6}', ['\u{10ca6}', '\0', '\0']),
-        ('\u{10ce7}', ['\u{10ca7}', '\0', '\0']), ('\u{10ce8}', ['\u{10ca8}', '\0', '\0']),
-        ('\u{10ce9}', ['\u{10ca9}', '\0', '\0']), ('\u{10cea}', ['\u{10caa}', '\0', '\0']),
-        ('\u{10ceb}', ['\u{10cab}', '\0', '\0']), ('\u{10cec}', ['\u{10cac}', '\0', '\0']),
-        ('\u{10ced}', ['\u{10cad}', '\0', '\0']), ('\u{10cee}', ['\u{10cae}', '\0', '\0']),
-        ('\u{10cef}', ['\u{10caf}', '\0', '\0']), ('\u{10cf0}', ['\u{10cb0}', '\0', '\0']),
-        ('\u{10cf1}', ['\u{10cb1}', '\0', '\0']), ('\u{10cf2}', ['\u{10cb2}', '\0', '\0']),
-        ('\u{118c0}', ['\u{118a0}', '\0', '\0']), ('\u{118c1}', ['\u{118a1}', '\0', '\0']),
-        ('\u{118c2}', ['\u{118a2}', '\0', '\0']), ('\u{118c3}', ['\u{118a3}', '\0', '\0']),
-        ('\u{118c4}', ['\u{118a4}', '\0', '\0']), ('\u{118c5}', ['\u{118a5}', '\0', '\0']),
-        ('\u{118c6}', ['\u{118a6}', '\0', '\0']), ('\u{118c7}', ['\u{118a7}', '\0', '\0']),
-        ('\u{118c8}', ['\u{118a8}', '\0', '\0']), ('\u{118c9}', ['\u{118a9}', '\0', '\0']),
-        ('\u{118ca}', ['\u{118aa}', '\0', '\0']), ('\u{118cb}', ['\u{118ab}', '\0', '\0']),
-        ('\u{118cc}', ['\u{118ac}', '\0', '\0']), ('\u{118cd}', ['\u{118ad}', '\0', '\0']),
-        ('\u{118ce}', ['\u{118ae}', '\0', '\0']), ('\u{118cf}', ['\u{118af}', '\0', '\0']),
-        ('\u{118d0}', ['\u{118b0}', '\0', '\0']), ('\u{118d1}', ['\u{118b1}', '\0', '\0']),
-        ('\u{118d2}', ['\u{118b2}', '\0', '\0']), ('\u{118d3}', ['\u{118b3}', '\0', '\0']),
-        ('\u{118d4}', ['\u{118b4}', '\0', '\0']), ('\u{118d5}', ['\u{118b5}', '\0', '\0']),
-        ('\u{118d6}', ['\u{118b6}', '\0', '\0']), ('\u{118d7}', ['\u{118b7}', '\0', '\0']),
-        ('\u{118d8}', ['\u{118b8}', '\0', '\0']), ('\u{118d9}', ['\u{118b9}', '\0', '\0']),
-        ('\u{118da}', ['\u{118ba}', '\0', '\0']), ('\u{118db}', ['\u{118bb}', '\0', '\0']),
-        ('\u{118dc}', ['\u{118bc}', '\0', '\0']), ('\u{118dd}', ['\u{118bd}', '\0', '\0']),
-        ('\u{118de}', ['\u{118be}', '\0', '\0']), ('\u{118df}', ['\u{118bf}', '\0', '\0']),
-        ('\u{16e60}', ['\u{16e40}', '\0', '\0']), ('\u{16e61}', ['\u{16e41}', '\0', '\0']),
-        ('\u{16e62}', ['\u{16e42}', '\0', '\0']), ('\u{16e63}', ['\u{16e43}', '\0', '\0']),
-        ('\u{16e64}', ['\u{16e44}', '\0', '\0']), ('\u{16e65}', ['\u{16e45}', '\0', '\0']),
-        ('\u{16e66}', ['\u{16e46}', '\0', '\0']), ('\u{16e67}', ['\u{16e47}', '\0', '\0']),
-        ('\u{16e68}', ['\u{16e48}', '\0', '\0']), ('\u{16e69}', ['\u{16e49}', '\0', '\0']),
-        ('\u{16e6a}', ['\u{16e4a}', '\0', '\0']), ('\u{16e6b}', ['\u{16e4b}', '\0', '\0']),
-        ('\u{16e6c}', ['\u{16e4c}', '\0', '\0']), ('\u{16e6d}', ['\u{16e4d}', '\0', '\0']),
-        ('\u{16e6e}', ['\u{16e4e}', '\0', '\0']), ('\u{16e6f}', ['\u{16e4f}', '\0', '\0']),
-        ('\u{16e70}', ['\u{16e50}', '\0', '\0']), ('\u{16e71}', ['\u{16e51}', '\0', '\0']),
-        ('\u{16e72}', ['\u{16e52}', '\0', '\0']), ('\u{16e73}', ['\u{16e53}', '\0', '\0']),
-        ('\u{16e74}', ['\u{16e54}', '\0', '\0']), ('\u{16e75}', ['\u{16e55}', '\0', '\0']),
-        ('\u{16e76}', ['\u{16e56}', '\0', '\0']), ('\u{16e77}', ['\u{16e57}', '\0', '\0']),
-        ('\u{16e78}', ['\u{16e58}', '\0', '\0']), ('\u{16e79}', ['\u{16e59}', '\0', '\0']),
-        ('\u{16e7a}', ['\u{16e5a}', '\0', '\0']), ('\u{16e7b}', ['\u{16e5b}', '\0', '\0']),
-        ('\u{16e7c}', ['\u{16e5c}', '\0', '\0']), ('\u{16e7d}', ['\u{16e5d}', '\0', '\0']),
-        ('\u{16e7e}', ['\u{16e5e}', '\0', '\0']), ('\u{16e7f}', ['\u{16e5f}', '\0', '\0']),
-        ('\u{1e922}', ['\u{1e900}', '\0', '\0']), ('\u{1e923}', ['\u{1e901}', '\0', '\0']),
-        ('\u{1e924}', ['\u{1e902}', '\0', '\0']), ('\u{1e925}', ['\u{1e903}', '\0', '\0']),
-        ('\u{1e926}', ['\u{1e904}', '\0', '\0']), ('\u{1e927}', ['\u{1e905}', '\0', '\0']),
-        ('\u{1e928}', ['\u{1e906}', '\0', '\0']), ('\u{1e929}', ['\u{1e907}', '\0', '\0']),
-        ('\u{1e92a}', ['\u{1e908}', '\0', '\0']), ('\u{1e92b}', ['\u{1e909}', '\0', '\0']),
-        ('\u{1e92c}', ['\u{1e90a}', '\0', '\0']), ('\u{1e92d}', ['\u{1e90b}', '\0', '\0']),
-        ('\u{1e92e}', ['\u{1e90c}', '\0', '\0']), ('\u{1e92f}', ['\u{1e90d}', '\0', '\0']),
-        ('\u{1e930}', ['\u{1e90e}', '\0', '\0']), ('\u{1e931}', ['\u{1e90f}', '\0', '\0']),
-        ('\u{1e932}', ['\u{1e910}', '\0', '\0']), ('\u{1e933}', ['\u{1e911}', '\0', '\0']),
-        ('\u{1e934}', ['\u{1e912}', '\0', '\0']), ('\u{1e935}', ['\u{1e913}', '\0', '\0']),
-        ('\u{1e936}', ['\u{1e914}', '\0', '\0']), ('\u{1e937}', ['\u{1e915}', '\0', '\0']),
-        ('\u{1e938}', ['\u{1e916}', '\0', '\0']), ('\u{1e939}', ['\u{1e917}', '\0', '\0']),
-        ('\u{1e93a}', ['\u{1e918}', '\0', '\0']), ('\u{1e93b}', ['\u{1e919}', '\0', '\0']),
-        ('\u{1e93c}', ['\u{1e91a}', '\0', '\0']), ('\u{1e93d}', ['\u{1e91b}', '\0', '\0']),
-        ('\u{1e93e}', ['\u{1e91c}', '\0', '\0']), ('\u{1e93f}', ['\u{1e91d}', '\0', '\0']),
-        ('\u{1e940}', ['\u{1e91e}', '\0', '\0']), ('\u{1e941}', ['\u{1e91f}', '\0', '\0']),
-        ('\u{1e942}', ['\u{1e920}', '\0', '\0']), ('\u{1e943}', ['\u{1e921}', '\0', '\0'])
-    ];
-}
diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py
deleted file mode 100755
index 97df92a..0000000
--- a/src/libcore/unicode/unicode.py
+++ /dev/null
@@ -1,878 +0,0 @@
-#!/usr/bin/env python
-
-"""
-Regenerate Unicode tables (tables.rs).
-"""
-
-# This script uses the Unicode tables as defined
-# in the UnicodeFiles class.
-
-# Since this should not require frequent updates, we just store this
-# out-of-line and check the tables.rs file into git.
-
-# Note that the "curl" program is required for operation.
-# This script is compatible with Python 2.7 and 3.x.
-
-import argparse
-import datetime
-import fileinput
-import itertools
-import os
-import re
-import textwrap
-import subprocess
-
-from collections import defaultdict, namedtuple
-
-try:
-    # Python 3
-    from itertools import zip_longest
-    from io import StringIO
-except ImportError:
-    # Python 2 compatibility
-    zip_longest = itertools.izip_longest
-    from StringIO import StringIO
-
-try:
-    # Completely optional type hinting
-    # (Python 2 compatible using comments,
-    # see: https://mypy.readthedocs.io/en/latest/python2.html)
-    # This is very helpful in typing-aware IDE like PyCharm.
-    from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Set, Tuple
-except ImportError:
-    pass
-
-
-# We don't use enum.Enum because of Python 2.7 compatibility.
-class UnicodeFiles(object):
-    # ReadMe does not contain any Unicode data, we
-    # only use it to extract versions.
-    README = "ReadMe.txt"
-
-    DERIVED_CORE_PROPERTIES = "DerivedCoreProperties.txt"
-    DERIVED_NORMALIZATION_PROPS = "DerivedNormalizationProps.txt"
-    PROPS = "PropList.txt"
-    SCRIPTS = "Scripts.txt"
-    SPECIAL_CASING = "SpecialCasing.txt"
-    UNICODE_DATA = "UnicodeData.txt"
-
-
-# The order doesn't really matter (Python < 3.6 won't preserve it),
-# we only want to aggregate all the file names.
-ALL_UNICODE_FILES = tuple(
-    value for name, value in UnicodeFiles.__dict__.items()
-    if not name.startswith("_")
-)
-
-assert len(ALL_UNICODE_FILES) == 7, "Unexpected number of unicode files"
-
-# The directory this file is located in.
-THIS_DIR = os.path.dirname(os.path.realpath(__file__))
-
-# Where to download the Unicode data.  The downloaded files
-# will be placed in sub-directories named after Unicode version.
-FETCH_DIR = os.path.join(THIS_DIR, "downloaded")
-
-FETCH_URL_LATEST = "ftp://ftp.unicode.org/Public/UNIDATA/{filename}"
-FETCH_URL_VERSION = "ftp://ftp.unicode.org/Public/{version}/ucd/{filename}"
-
-PREAMBLE = """\
-// NOTE: The following code was generated by "./unicode.py", do not edit directly
-
-#![allow(missing_docs, non_upper_case_globals, non_snake_case, clippy::unreadable_literal)]
-
-use crate::unicode::bool_trie::{{BoolTrie, SmallBoolTrie}};
-use crate::unicode::version::UnicodeVersion;
-""".format(year=datetime.datetime.now().year)
-
-# Mapping taken from Table 12 from:
-# http://www.unicode.org/reports/tr44/#General_Category_Values
-EXPANDED_CATEGORIES = {
-    "Lu": ["LC", "L"], "Ll": ["LC", "L"], "Lt": ["LC", "L"],
-    "Lm": ["L"], "Lo": ["L"],
-    "Mn": ["M"], "Mc": ["M"], "Me": ["M"],
-    "Nd": ["N"], "Nl": ["N"], "No": ["N"],
-    "Pc": ["P"], "Pd": ["P"], "Ps": ["P"], "Pe": ["P"],
-    "Pi": ["P"], "Pf": ["P"], "Po": ["P"],
-    "Sm": ["S"], "Sc": ["S"], "Sk": ["S"], "So": ["S"],
-    "Zs": ["Z"], "Zl": ["Z"], "Zp": ["Z"],
-    "Cc": ["C"], "Cf": ["C"], "Cs": ["C"], "Co": ["C"], "Cn": ["C"],
-}
-
-# This is the (inclusive) range of surrogate codepoints.
-# These are not valid Rust characters.
-SURROGATE_CODEPOINTS_RANGE = (0xd800, 0xdfff)
-
-UnicodeData = namedtuple(
-    "UnicodeData", (
-        # Conversions:
-        "to_upper", "to_lower", "to_title",
-
-        # Decompositions: canonical decompositions, compatibility decomp
-        "canon_decomp", "compat_decomp",
-
-        # Grouped: general categories and combining characters
-        "general_categories", "combines",
-    )
-)
-
-UnicodeVersion = namedtuple(
-    "UnicodeVersion", ("major", "minor", "micro", "as_str")
-)
-
-
-def fetch_files(version=None):
-    # type: (str) -> UnicodeVersion
-    """
-    Fetch all the Unicode files from unicode.org.
-
-    This will use cached files (stored in `FETCH_DIR`) if they exist,
-    creating them if they don't.  In any case, the Unicode version
-    is always returned.
-
-    :param version: The desired Unicode version, as string.
-        (If None, defaults to latest final release available,
-         querying the unicode.org service).
-    """
-    have_version = check_stored_version(version)
-    if have_version:
-        return have_version
-
-    if version:
-        # Check if the desired version exists on the server.
-        get_fetch_url = lambda name: FETCH_URL_VERSION.format(version=version, filename=name)
-    else:
-        # Extract the latest version.
-        get_fetch_url = lambda name: FETCH_URL_LATEST.format(filename=name)
-
-    readme_url = get_fetch_url(UnicodeFiles.README)
-
-    print("Fetching: {}".format(readme_url))
-    readme_content = subprocess.check_output(("curl", readme_url))
-
-    unicode_version = parse_readme_unicode_version(
-        readme_content.decode("utf8")
-    )
-
-    download_dir = get_unicode_dir(unicode_version)
-    if not os.path.exists(download_dir):
-        # For 2.7 compat, we don't use `exist_ok=True`.
-        os.makedirs(download_dir)
-
-    for filename in ALL_UNICODE_FILES:
-        file_path = get_unicode_file_path(unicode_version, filename)
-
-        if os.path.exists(file_path):
-            # Assume file on the server didn't change if it's been saved before.
-            continue
-
-        if filename == UnicodeFiles.README:
-            with open(file_path, "wb") as fd:
-                fd.write(readme_content)
-        else:
-            url = get_fetch_url(filename)
-            print("Fetching: {}".format(url))
-            subprocess.check_call(("curl", "-o", file_path, url))
-
-    return unicode_version
-
-
-def check_stored_version(version):
-    # type: (Optional[str]) -> Optional[UnicodeVersion]
-    """
-    Given desired Unicode version, return the version
-    if stored files are all present, and `None` otherwise.
-    """
-    if not version:
-        # If no desired version specified, we should check what's the latest
-        # version, skipping stored version checks.
-        return None
-
-    fetch_dir = os.path.join(FETCH_DIR, version)
-
-    for filename in ALL_UNICODE_FILES:
-        file_path = os.path.join(fetch_dir, filename)
-
-        if not os.path.exists(file_path):
-            return None
-
-    with open(os.path.join(fetch_dir, UnicodeFiles.README)) as fd:
-        return parse_readme_unicode_version(fd.read())
-
-
-def parse_readme_unicode_version(readme_content):
-    # type: (str) -> UnicodeVersion
-    """
-    Parse the Unicode version contained in their `ReadMe.txt` file.
-    """
-    # "Raw string" is necessary for \d not being treated as escape char
-    # (for the sake of compat with future Python versions).
-    # See: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior
-    pattern = r"for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
-    groups = re.search(pattern, readme_content).groups()
-
-    return UnicodeVersion(*map(int, groups), as_str=".".join(groups))
-
-
-def get_unicode_dir(unicode_version):
-    # type: (UnicodeVersion) -> str
-    """
-    Indicate in which parent dir the Unicode data files should be stored.
-
-    This returns a full, absolute path.
-    """
-    return os.path.join(FETCH_DIR, unicode_version.as_str)
-
-
-def get_unicode_file_path(unicode_version, filename):
-    # type: (UnicodeVersion, str) -> str
-    """
-    Indicate where the Unicode data file should be stored.
-    """
-    return os.path.join(get_unicode_dir(unicode_version), filename)
-
-
-def is_surrogate(n):
-    # type: (int) -> bool
-    """
-    Tell if given codepoint is a surrogate (not a valid Rust character).
-    """
-    return SURROGATE_CODEPOINTS_RANGE[0] <= n <= SURROGATE_CODEPOINTS_RANGE[1]
-
-
-def load_unicode_data(file_path):
-    # type: (str) -> UnicodeData
-    """
-    Load main Unicode data.
-    """
-    # Conversions
-    to_lower = {}   # type: Dict[int, Tuple[int, int, int]]
-    to_upper = {}   # type: Dict[int, Tuple[int, int, int]]
-    to_title = {}   # type: Dict[int, Tuple[int, int, int]]
-
-    # Decompositions
-    compat_decomp = {}   # type: Dict[int, List[int]]
-    canon_decomp = {}    # type: Dict[int, List[int]]
-
-    # Combining characters
-    # FIXME: combines are not used
-    combines = defaultdict(set)   # type: Dict[str, Set[int]]
-
-    # Categories
-    general_categories = defaultdict(set)   # type: Dict[str, Set[int]]
-    category_assigned_codepoints = set()    # type: Set[int]
-
-    all_codepoints = {}
-
-    range_start = -1
-
-    for line in fileinput.input(file_path):
-        data = line.split(";")
-        if len(data) != 15:
-            continue
-        codepoint = int(data[0], 16)
-        if is_surrogate(codepoint):
-            continue
-        if range_start >= 0:
-            for i in range(range_start, codepoint):
-                all_codepoints[i] = data
-            range_start = -1
-        if data[1].endswith(", First>"):
-            range_start = codepoint
-            continue
-        all_codepoints[codepoint] = data
-
-    for code, data in all_codepoints.items():
-        (code_org, name, gencat, combine, bidi,
-         decomp, deci, digit, num, mirror,
-         old, iso, upcase, lowcase, titlecase) = data
-
-        # Generate char to char direct common and simple conversions:
-
-        # Uppercase to lowercase
-        if lowcase != "" and code_org != lowcase:
-            to_lower[code] = (int(lowcase, 16), 0, 0)
-
-        # Lowercase to uppercase
-        if upcase != "" and code_org != upcase:
-            to_upper[code] = (int(upcase, 16), 0, 0)
-
-        # Title case
-        if titlecase.strip() != "" and code_org != titlecase:
-            to_title[code] = (int(titlecase, 16), 0, 0)
-
-        # Store decomposition, if given
-        if decomp:
-            decompositions = decomp.split()[1:]
-            decomp_code_points = [int(i, 16) for i in decompositions]
-
-            if decomp.startswith("<"):
-                # Compatibility decomposition
-                compat_decomp[code] = decomp_code_points
-            else:
-                # Canonical decomposition
-                canon_decomp[code] = decomp_code_points
-
-        # Place letter in categories as appropriate.
-        for cat in itertools.chain((gencat, ), EXPANDED_CATEGORIES.get(gencat, [])):
-            general_categories[cat].add(code)
-            category_assigned_codepoints.add(code)
-
-        # Record combining class, if any.
-        if combine != "0":
-            combines[combine].add(code)
-
-    # Generate Not_Assigned from Assigned.
-    general_categories["Cn"] = get_unassigned_codepoints(category_assigned_codepoints)
-
-    # Other contains Not_Assigned
-    general_categories["C"].update(general_categories["Cn"])
-
-    grouped_categories = group_categories(general_categories)
-
-    # FIXME: combines are not used
-    return UnicodeData(
-        to_lower=to_lower, to_upper=to_upper, to_title=to_title,
-        compat_decomp=compat_decomp, canon_decomp=canon_decomp,
-        general_categories=grouped_categories, combines=combines,
-    )
-
-
-def load_special_casing(file_path, unicode_data):
-    # type: (str, UnicodeData) -> None
-    """
-    Load special casing data and enrich given Unicode data.
-    """
-    for line in fileinput.input(file_path):
-        data = line.split("#")[0].split(";")
-        if len(data) == 5:
-            code, lower, title, upper, _comment = data
-        elif len(data) == 6:
-            code, lower, title, upper, condition, _comment = data
-            if condition.strip():  # Only keep unconditional mappins
-                continue
-        else:
-            continue
-        code = code.strip()
-        lower = lower.strip()
-        title = title.strip()
-        upper = upper.strip()
-        key = int(code, 16)
-        for (map_, values) in ((unicode_data.to_lower, lower),
-                               (unicode_data.to_upper, upper),
-                               (unicode_data.to_title, title)):
-            if values != code:
-                split = values.split()
-
-                codepoints = list(itertools.chain(
-                    (int(i, 16) for i in split),
-                    (0 for _ in range(len(split), 3))
-                ))
-
-                assert len(codepoints) == 3
-                map_[key] = codepoints
-
-
-def group_categories(mapping):
-    # type: (Dict[Any, Iterable[int]]) -> Dict[str, List[Tuple[int, int]]]
-    """
-    Group codepoints mapped in "categories".
-    """
-    return {category: group_codepoints(codepoints)
-            for category, codepoints in mapping.items()}
-
-
-def group_codepoints(codepoints):
-    # type: (Iterable[int]) -> List[Tuple[int, int]]
-    """
-    Group integral values into continuous, disjoint value ranges.
-
-    Performs value deduplication.
-
-    :return: sorted list of pairs denoting start and end of codepoint
-        group values, both ends inclusive.
-
-    >>> group_codepoints([1, 2, 10, 11, 12, 3, 4])
-    [(1, 4), (10, 12)]
-    >>> group_codepoints([1])
-    [(1, 1)]
-    >>> group_codepoints([1, 5, 6])
-    [(1, 1), (5, 6)]
-    >>> group_codepoints([])
-    []
-    """
-    sorted_codes = sorted(set(codepoints))
-    result = []     # type: List[Tuple[int, int]]
-
-    if not sorted_codes:
-        return result
-
-    next_codes = sorted_codes[1:]
-    start_code = sorted_codes[0]
-
-    for code, next_code in zip_longest(sorted_codes, next_codes, fillvalue=None):
-        if next_code is None or next_code - code != 1:
-            result.append((start_code, code))
-            start_code = next_code
-
-    return result
-
-
-def ungroup_codepoints(codepoint_pairs):
-    # type: (Iterable[Tuple[int, int]]) -> List[int]
-    """
-    The inverse of group_codepoints -- produce a flat list of values
-    from value range pairs.
-
-    >>> ungroup_codepoints([(1, 4), (10, 12)])
-    [1, 2, 3, 4, 10, 11, 12]
-    >>> ungroup_codepoints([(1, 1), (5, 6)])
-    [1, 5, 6]
-    >>> ungroup_codepoints(group_codepoints([1, 2, 7, 8]))
-    [1, 2, 7, 8]
-    >>> ungroup_codepoints([])
-    []
-    """
-    return list(itertools.chain.from_iterable(
-        range(lo, hi + 1) for lo, hi in codepoint_pairs
-    ))
-
-
-def get_unassigned_codepoints(assigned_codepoints):
-    # type: (Set[int]) -> Set[int]
-    """
-    Given a set of "assigned" codepoints, return a set
-    of these that are not in assigned and not surrogate.
-    """
-    return {i for i in range(0, 0x110000)
-            if i not in assigned_codepoints and not is_surrogate(i)}
-
-
-def generate_table_lines(items, indent, wrap=98):
-    # type: (Iterable[str], int, int) -> Iterator[str]
-    """
-    Given table items, generate wrapped lines of text with comma-separated items.
-
-    This is a generator function.
-
-    :param wrap: soft wrap limit (characters per line), integer.
-    """
-    line = " " * indent
-    first = True
-    for item in items:
-        if len(line) + len(item) < wrap:
-            if first:
-                line += item
-            else:
-                line += ", " + item
-            first = False
-        else:
-            yield line + ",\n"
-            line = " " * indent + item
-
-    yield line
-
-
-def load_properties(file_path, interesting_props):
-    # type: (str, Iterable[str]) -> Dict[str, List[Tuple[int, int]]]
-    """
-    Load properties data and return in grouped form.
-    """
-    props = defaultdict(list)   # type: Dict[str, List[Tuple[int, int]]]
-    # "Raw string" is necessary for `\.` and `\w` not to be treated as escape chars
-    # (for the sake of compat with future Python versions).
-    # See: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior
-    re1 = re.compile(r"^ *([0-9A-F]+) *; *(\w+)")
-    re2 = re.compile(r"^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)")
-
-    for line in fileinput.input(file_path):
-        match = re1.match(line) or re2.match(line)
-        if match:
-            groups = match.groups()
-
-            if len(groups) == 2:
-                # `re1` matched (2 groups).
-                d_lo, prop = groups
-                d_hi = d_lo
-            else:
-                d_lo, d_hi, prop = groups
-        else:
-            continue
-
-        if interesting_props and prop not in interesting_props:
-            continue
-
-        lo_value = int(d_lo, 16)
-        hi_value = int(d_hi, 16)
-
-        props[prop].append((lo_value, hi_value))
-
-    # Optimize if possible.
-    for prop in props:
-        props[prop] = group_codepoints(ungroup_codepoints(props[prop]))
-
-    return props
-
-
-def escape_char(c):
-    # type: (int) -> str
-    r"""
-    Escape a codepoint for use as Rust char literal.
-
-    Outputs are OK to use as Rust source code as char literals
-    and they also include necessary quotes.
-
-    >>> escape_char(97)
-    "'\\u{61}'"
-    >>> escape_char(0)
-    "'\\0'"
-    """
-    return r"'\u{%x}'" % c if c != 0 else r"'\0'"
-
-
-def format_char_pair(pair):
-    # type: (Tuple[int, int]) -> str
-    """
-    Format a pair of two Rust chars.
-    """
-    return "(%s,%s)" % (escape_char(pair[0]), escape_char(pair[1]))
-
-
-def generate_table(
-    name,   # type: str
-    items,  # type: List[Tuple[int, int]]
-    decl_type="&[(char, char)]",    # type: str
-    is_pub=True,                    # type: bool
-    format_item=format_char_pair,   # type: Callable[[Tuple[int, int]], str]
-):
-    # type: (...) -> Iterator[str]
-    """
-    Generate a nicely formatted Rust constant "table" array.
-
-    This generates actual Rust code.
-    """
-    pub_string = ""
-    if is_pub:
-        pub_string = "pub "
-
-    yield "\n"
-    yield "    #[rustfmt::skip]\n"
-    yield "    %sconst %s: %s = &[\n" % (pub_string, name, decl_type)
-
-    data = []
-    first = True
-    for item in items:
-        if not first:
-            data.append(",")
-        first = False
-        data.extend(format_item(item))
-
-    for table_line in generate_table_lines("".join(data).split(","), 8):
-        yield table_line
-
-    yield "\n    ];\n"
-
-
-def compute_trie(raw_data, chunk_size):
-    # type: (List[int], int) -> Tuple[List[int], List[int]]
-    """
-    Compute postfix-compressed trie.
-
-    See: bool_trie.rs for more details.
-
-    >>> compute_trie([1, 2, 3, 1, 2, 3, 4, 5, 6], 3)
-    ([0, 0, 1], [1, 2, 3, 4, 5, 6])
-    >>> compute_trie([1, 2, 3, 1, 2, 4, 4, 5, 6], 3)
-    ([0, 1, 2], [1, 2, 3, 1, 2, 4, 4, 5, 6])
-    """
-    root = []
-    childmap = {}       # type: Dict[Tuple[int, ...], int]
-    child_data = []
-
-    assert len(raw_data) % chunk_size == 0, "Chunks must be equally sized"
-
-    for i in range(len(raw_data) // chunk_size):
-        data = raw_data[i * chunk_size : (i + 1) * chunk_size]
-
-        # Postfix compression of child nodes (data chunks)
-        # (identical child nodes are shared).
-
-        # Make a tuple out of the list so it's hashable.
-        child = tuple(data)
-        if child not in childmap:
-            childmap[child] = len(childmap)
-            child_data.extend(data)
-
-        root.append(childmap[child])
-
-    return root, child_data
-
-
-def generate_bool_trie(name, codepoint_ranges, is_pub=False):
-    # type: (str, List[Tuple[int, int]], bool) -> Iterator[str]
-    """
-    Generate Rust code for BoolTrie struct.
-
-    This yields string fragments that should be joined to produce
-    the final string.
-
-    See: `bool_trie.rs`.
-    """
-    chunk_size = 64
-    rawdata = [False] * 0x110000
-    for (lo, hi) in codepoint_ranges:
-        for cp in range(lo, hi + 1):
-            rawdata[cp] = True
-
-    # Convert to bitmap chunks of `chunk_size` bits each.
-    chunks = []
-    for i in range(0x110000 // chunk_size):
-        chunk = 0
-        for j in range(chunk_size):
-            if rawdata[i * chunk_size + j]:
-                chunk |= 1 << j
-        chunks.append(chunk)
-
-    pub_string = ""
-    if is_pub:
-        pub_string = "pub "
-
-    yield "\n"
-    yield "    #[rustfmt::skip]\n"
-    yield "    %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name)
-    yield "        r1: [\n"
-    data = ("0x%016x" % chunk for chunk in chunks[:0x800 // chunk_size])
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    # 0x800..0x10000 trie
-    (r2, r3) = compute_trie(chunks[0x800 // chunk_size : 0x10000 // chunk_size], 64 // chunk_size)
-    yield "        r2: [\n"
-    data = map(str, r2)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    yield "        r3: &[\n"
-    data = ("0x%016x" % node for node in r3)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    # 0x10000..0x110000 trie
-    (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size],
-                             64 // chunk_size)
-    (r4, r5) = compute_trie(mid, 64)
-
-    yield "        r4: [\n"
-    data = map(str, r4)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    yield "        r5: &[\n"
-    data = map(str, r5)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    yield "        r6: &[\n"
-    data = ("0x%016x" % node for node in r6)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    yield "    };\n"
-
-
-def generate_small_bool_trie(name, codepoint_ranges, is_pub=False):
-    # type: (str, List[Tuple[int, int]], bool) -> Iterator[str]
-    """
-    Generate Rust code for `SmallBoolTrie` struct.
-
-    See: `bool_trie.rs`.
-    """
-    last_chunk = max(hi // 64 for (lo, hi) in codepoint_ranges)
-    n_chunks = last_chunk + 1
-    chunks = [0] * n_chunks
-    for (lo, hi) in codepoint_ranges:
-        for cp in range(lo, hi + 1):
-            assert cp // 64 < len(chunks)
-            chunks[cp // 64] |= 1 << (cp & 63)
-
-    pub_string = ""
-    if is_pub:
-        pub_string = "pub "
-
-    yield "\n"
-    yield "    #[rustfmt::skip]\n"
-    yield ("    %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n"
-           % (pub_string, name))
-
-    (r1, r2) = compute_trie(chunks, 1)
-
-    yield "        r1: &[\n"
-    data = (str(node) for node in r1)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    yield "        r2: &[\n"
-    data = ("0x%016x" % node for node in r2)
-    for fragment in generate_table_lines(data, 12):
-        yield fragment
-    yield "\n        ],\n"
-
-    yield "    };\n"
-
-
-def generate_property_module(mod, grouped_categories, category_subset):
-    # type: (str, Dict[str, List[Tuple[int, int]]], Iterable[str]) -> Iterator[str]
-    """
-    Generate Rust code for module defining properties.
-    """
-
-    yield "pub(crate) mod %s {" % mod
-    for cat in sorted(category_subset):
-        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])
-
-        for fragment in generator:
-            yield fragment
-
-        yield "\n"
-        yield "    pub fn %s(c: char) -> bool {\n" % cat
-        yield "        %s_table.lookup(c)\n" % cat
-        yield "    }\n"
-
-    yield "}\n\n"
-
-
-def generate_conversions_module(unicode_data):
-    # type: (UnicodeData) -> Iterator[str]
-    """
-    Generate Rust code for module defining conversions.
-    """
-
-    yield "pub(crate) mod conversions {"
-    yield """
-    pub fn to_lower(c: char) -> [char; 3] {
-        match bsearch_case_table(c, to_lowercase_table) {
-            None => [c, '\\0', '\\0'],
-            Some(index) => to_lowercase_table[index].1,
-        }
-    }
-
-    pub fn to_upper(c: char) -> [char; 3] {
-        match bsearch_case_table(c, to_uppercase_table) {
-            None => [c, '\\0', '\\0'],
-            Some(index) => to_uppercase_table[index].1,
-        }
-    }
-
-    fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
-        table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
-    }\n"""
-
-    decl_type = "&[(char, [char; 3])]"
-    format_conversion = lambda x: "({},[{},{},{}])".format(*(
-        escape_char(c) for c in (x[0], x[1][0], x[1][1], x[1][2])
-    ))
-
-    for fragment in generate_table(
-        name="to_lowercase_table",
-        items=sorted(unicode_data.to_lower.items(), key=lambda x: x[0]),
-        decl_type=decl_type,
-        is_pub=False,
-        format_item=format_conversion
-    ):
-        yield fragment
-
-    for fragment in generate_table(
-        name="to_uppercase_table",
-        items=sorted(unicode_data.to_upper.items(), key=lambda x: x[0]),
-        decl_type=decl_type,
-        is_pub=False,
-        format_item=format_conversion
-    ):
-        yield fragment
-
-    yield "}\n"
-
-
-def parse_args():
-    # type: () -> argparse.Namespace
-    """
-    Parse command line arguments.
-    """
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument("-v", "--version", default=None, type=str,
-                        help="Unicode version to use (if not specified,"
-                             " defaults to latest release).")
-
-    return parser.parse_args()
-
-
-def main():
-    # type: () -> None
-    """
-    Script entry point.
-    """
-    args = parse_args()
-
-    unicode_version = fetch_files(args.version)
-    print("Using Unicode version: {}".format(unicode_version.as_str))
-
-    # All the writing happens entirely in memory, we only write to file
-    # once we have generated the file content (it's not very large, <1 MB).
-    buf = StringIO()
-    buf.write(PREAMBLE)
-
-    unicode_version_notice = textwrap.dedent("""
-    /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
-    /// `char` and `str` methods are based on.
-    #[unstable(feature = "unicode_version", issue = "49726")]
-    pub const UNICODE_VERSION: UnicodeVersion =
-        UnicodeVersion {{ major: {v.major}, minor: {v.minor}, micro: {v.micro}, _priv: () }};
-    """).format(v=unicode_version)
-    buf.write(unicode_version_notice)
-
-    get_path = lambda f: get_unicode_file_path(unicode_version, f)
-
-    unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA))
-    load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data)
-
-    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"})
-
-    # 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"])
-    ):
-        for fragment in generate_property_module(name, categories, category_subset):
-            buf.write(fragment)
-
-    for fragment in generate_conversions_module(unicode_data):
-        buf.write(fragment)
-
-    tables_rs_path = os.path.join(THIS_DIR, "tables.rs")
-
-    # Actually write out the file content.
-    # Will overwrite the file if it exists.
-    with open(tables_rs_path, "w") as fd:
-        fd.write(buf.getvalue())
-
-    print("Regenerated tables.rs.")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/src/libcore/unicode/unicode_data.rs b/src/libcore/unicode/unicode_data.rs
new file mode 100644
index 0000000..da4cd4e
--- /dev/null
+++ b/src/libcore/unicode/unicode_data.rs
@@ -0,0 +1,2343 @@
+///! This file is generated by src/tools/unicode-table-generator; do not edit manually!
+use super::range_search;
+
+pub const UNICODE_VERSION: (u32, u32, u32) = (12, 1, 0);
+
+#[rustfmt::skip]
+pub mod alphabetic {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (190, 37);
+    static BITSET_CHUNKS_MAP: [u8; 187] = [
+        6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 49, 49, 49, 49, 49, 49, 36, 49, 49, 49, 49,
+        49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 47, 49, 30, 8, 49, 49, 49, 49,
+        49, 49, 49, 49, 49, 49, 45, 0, 0, 0, 0, 0, 0, 0, 0, 4, 35, 17, 31, 16, 25, 24, 26, 13, 15,
+        44, 27, 0, 0, 49, 11, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 49, 49, 49, 49, 49, 48,
+        42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0,
+        0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+        49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 41, 49, 49, 49,
+        43, 22, 49, 49, 49, 49, 40, 49, 49, 49, 49, 49, 49, 46,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 50] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 248, 241, 38, 40],
+        [0, 0, 0, 0, 0, 0, 0, 0, 108, 133, 110, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 190, 200, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 248, 248, 248, 248, 248, 205, 248, 23, 134, 245, 68, 237],
+        [0, 0, 179, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 103, 99, 176, 248, 248, 248, 248, 248, 248, 248, 61, 0, 151, 217, 178],
+        [0, 145, 28, 0, 168, 221, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [48, 77, 248, 165, 201, 120, 184, 137, 91, 175, 143, 83, 206, 196, 248, 56],
+        [53, 0, 0, 0, 126, 15, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
+        [59, 54, 127, 199, 167, 186, 157, 114, 154, 84, 160, 115, 158, 66, 155, 21],
+        [62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [91, 129, 164, 101, 248, 248, 248, 79, 248, 248, 248, 248, 230, 128, 135, 117],
+        [97, 0, 220, 144, 0, 0, 212, 44, 142, 240, 30, 97, 0, 0, 0, 0],
+        [116, 247, 219, 171, 188, 248, 104, 190, 0, 0, 0, 0, 0, 0, 0, 0],
+        [141, 185, 88, 0, 149, 213, 22, 0, 0, 0, 0, 89, 0, 0, 0, 0],
+        [147, 90, 35, 82, 98, 0, 153, 0, 85, 119, 29, 45, 86, 71, 18, 0],
+        [150, 32, 248, 107, 0, 81, 0, 0, 0, 0, 227, 17, 211, 105, 231, 19],
+        [162, 41, 161, 69, 163, 173, 123, 73, 106, 14, 124, 37, 1, 187, 121, 0],
+        [172, 240, 228, 170, 248, 248, 248, 248, 248, 229, 138, 235, 234, 24, 222, 125],
+        [208, 233, 248, 74, 204, 64, 140, 232, 63, 0, 0, 0, 0, 0, 0, 0],
+        [220, 97, 202, 86, 94, 78, 203, 9, 226, 80, 46, 0, 183, 11, 174, 67],
+        [231, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248],
+        [247, 248, 248, 248, 248, 248, 248, 248, 248, 209, 225, 95, 76, 75, 180, 25],
+        [248, 5, 96, 50, 72, 87, 248, 26, 132, 0, 198, 51, 159, 42, 0, 0],
+        [248, 8, 72, 72, 49, 0, 0, 0, 0, 0, 0, 0, 194, 5, 0, 89],
+        [248, 36, 248, 7, 0, 0, 139, 31, 143, 3, 93, 0, 55, 0, 0, 0],
+        [248, 62, 248, 248, 248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [248, 118, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [248, 236, 166, 246, 136, 239, 248, 248, 248, 248, 215, 169, 182, 207, 214, 12],
+        [248, 248, 13, 130, 248, 248, 248, 248, 57, 146, 248, 65, 218, 248, 243, 177],
+        [248, 248, 191, 111, 197, 43, 0, 0, 248, 248, 248, 248, 91, 47, 0, 0],
+        [248, 248, 244, 248, 189, 223, 152, 70, 224, 210, 248, 148, 240, 242, 68, 100],
+        [248, 248, 248, 4, 248, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [248, 248, 248, 248, 35, 195, 248, 248, 248, 248, 248, 113, 0, 0, 0, 0],
+        [248, 248, 248, 248, 131, 240, 238, 109, 0, 181, 248, 122, 102, 216, 143, 27],
+        [248, 248, 248, 248, 248, 248, 86, 0, 248, 248, 248, 248, 248, 248, 248, 248],
+        [248, 248, 248, 248, 248, 248, 248, 248, 33, 0, 0, 0, 0, 0, 0, 0],
+        [248, 248, 248, 248, 248, 248, 248, 248, 97, 35, 0, 60, 65, 156, 16, 0],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 6, 0, 0, 0, 0, 0, 0],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 192, 248, 248, 248, 248, 248],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 20, 248, 248, 248, 248],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 72, 0, 0, 0, 0],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 81, 248, 248, 248],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 23, 0],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 193, 112],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 39],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 65],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 92],
+        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248],
+    ];
+    static BITSET: [u64; 249] = [
+        0, 1, 15, 17, 31, 63, 127, 179, 511, 1023, 2191, 4079, 4087, 8191, 8319, 16384, 65535,
+        131071, 262143, 4128527, 8388607, 8461767, 24870911, 67108863, 134217727, 276824575,
+        335544350, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823,
+        1140785663, 2147483647, 2147485627, 4026540127, 4294934783, 8589934591, 47244640256,
+        64548249055, 68191066527, 68719476735, 115913785343, 137438953215, 549755813888,
+        1095220854783, 1099511627711, 1099511627775, 2199023190016, 2199023255551, 4398046511103,
+        8641373536127, 8791831609343, 8795690369023, 8796093022207, 13198434443263, 17592186044415,
+        35184321757183, 70368744112128, 88094074470339, 140737488355327, 140737488355328,
+        141836999983103, 281474976710655, 563017343310239, 1125625028935679, 1125899906842623,
+        1688915364814303, 2119858418286774, 2251795522912255, 2251799813685247, 3377704004976767,
+        3509778554814463, 3905461007941631, 4503595333443583, 4503599627370495, 8796093022142464,
+        9006649498927104, 9007192812290047, 9007199254740991, 15762594400829440, 17169970223906821,
+        17732925109967239, 18014398491652207, 18014398509481983, 20266198323101808,
+        36027697507139583, 36028792723996672, 36028792728190975, 36028797018963967,
+        72057594037927935, 90071992547409919, 143851303137705983, 144053615424700415,
+        144115188075855868, 144115188075855871, 288230371860938751, 297241973452963840,
+        301749971126844416, 319718190147960832, 576460743713488896, 576460743847706622,
+        576460748008488959, 576460752303359999, 576460752303423486, 576460752303423487,
+        790380184120328175, 1152640029630136575, 1152917029519358975, 1152921504591118335,
+        1152921504606845055, 1152921504606846975, 1153765996922689951, 2161727885562420159,
+        2251241253188403424, 2295745090394464220, 2305570330330005503, 2305843004918726656,
+        2305843004919250943, 2305843009196916483, 2305843009213693951, 3457638613854978028,
+        4323455298678290390, 4557642822898941951, 4575692405780512767, 4602678814877679616,
+        4611686017001275199, 4611686018360336384, 4611686018427322368, 4611686018427387903,
+        4656722014700830719, 6843210385291930244, 6881498031078244479, 6908521828386340863,
+        8935141660164089791, 8935423131384840192, 9168765891372858879, 9169328841326329855,
+        9187201948305063935, 9187343239835811327, 9216616637413720063, 9223372036854775807,
+        9223372041149743103, 9223934986808197120, 10371930679322607615, 10502394331027995967,
+        11241233151490523135, 13006395723845991295, 13258596753222922239, 13609596598936928288,
+        13834776580305453567, 13907115649320091647, 14082190885810440174, 14123225865944680428,
+        16212958624174047247, 16412803692974677999, 16424062692043104238, 16424062692043104239,
+        16424062692043243502, 16424625641996804079, 16429129241624174575, 16717361816799141871,
+        16717361816799216127, 16788293510930366511, 17005555242810474495, 17293822569102704639,
+        17581979622616071300, 17870283321271910397, 17870283321406070975, 17870283321406128127,
+        17978369712463020031, 18158513764145585631, 18158781978395017215, 18194542490281852927,
+        18410715276682199039, 18410715276690587772, 18428729675200069631, 18428729675200069632,
+        18433233274827440127, 18437455399478099968, 18437736874452713471, 18442240474082181119,
+        18444492273895866367, 18445618173802708993, 18446181192473632767, 18446216308128218879,
+        18446462598732840928, 18446462598732840959, 18446462598732840960, 18446462599806582783,
+        18446462615912710143, 18446462667452317695, 18446463149025525759, 18446463629525450752,
+        18446463698110251007, 18446463698244468735, 18446464796682337663, 18446466966713532416,
+        18446466996779287551, 18446471394825862144, 18446471394825863167, 18446480190918885375,
+        18446498607738650623, 18446532967477018623, 18446602782178705022, 18446603336221163519,
+        18446603336221196287, 18446638520593285119, 18446673709243564031, 18446708893632430079,
+        18446740770879700992, 18446741595513422027, 18446741874686295551, 18446743249075830783,
+        18446743798965862398, 18446744056529672000, 18446744060816261120, 18446744068886102015,
+        18446744069414584320, 18446744069414601696, 18446744069414649855, 18446744069456527359,
+        18446744069548736512, 18446744069548802046, 18446744069683019775, 18446744069951455231,
+        18446744070421282815, 18446744070446333439, 18446744070475743231, 18446744070488326143,
+        18446744071553646463, 18446744071562067967, 18446744073696837631, 18446744073701162813,
+        18446744073707454463, 18446744073709027328, 18446744073709355007, 18446744073709419615,
+        18446744073709486080, 18446744073709520895, 18446744073709543424, 18446744073709550079,
+        18446744073709550595, 18446744073709551579, 18446744073709551599, 18446744073709551614,
+        18446744073709551615,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod case_ignorable {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 33);
+    static BITSET_CHUNKS_MAP: [u8; 125] = [
+        25, 14, 21, 30, 28, 4, 17, 23, 22, 0, 0, 16, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 3, 6, 9, 0, 7, 11, 32, 31, 26, 29, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
+        10, 0, 8, 0, 20, 0, 12, 0, 1,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 52],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 171, 2],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 88, 134, 38],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 102, 6, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 76, 26, 0, 146, 136, 79, 43, 117],
+        [0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 58, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 165, 97, 75, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 48, 0, 114, 0, 0],
+        [0, 0, 0, 0, 0, 170, 68, 0, 0, 7, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0],
+        [0, 0, 0, 28, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 133, 0, 0, 0, 0, 15, 160, 45, 84, 51, 78, 12, 109],
+        [0, 0, 11, 0, 0, 30, 161, 90, 35, 80, 0, 69, 173, 13, 81, 129],
+        [0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 131, 0, 85, 0, 148, 0, 175, 73, 0, 0, 0, 0, 0, 0, 0],
+        [20, 4, 62, 0, 118, 0, 0, 0, 32, 154, 145, 0, 124, 89, 67, 86],
+        [25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [59, 0, 0, 150, 70, 24, 132, 60, 100, 122, 163, 99, 0, 46, 0, 66],
+        [63, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0],
+        [71, 33, 0, 178, 123, 83, 120, 137, 121, 98, 121, 167, 153, 55, 3, 18],
+        [72, 149, 36, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [104, 133, 0, 110, 174, 105, 177, 166, 0, 0, 0, 0, 0, 0, 155, 139],
+        [107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [111, 50, 106, 0, 0, 0, 0, 0, 0, 0, 172, 179, 179, 112, 9, 0],
+        [113, 0, 0, 0, 0, 0, 0, 49, 142, 34, 31, 0, 0, 0, 0, 0],
+        [116, 0, 42, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [140, 93, 37, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0],
+        [159, 0, 101, 0, 158, 10, 29, 0, 0, 0, 0, 91, 0, 0, 0, 0],
+        [162, 56, 153, 54, 125, 53, 0, 27, 115, 21, 126, 19, 108, 144, 127, 8],
+        [168, 41, 151, 5, 0, 0, 157, 39, 156, 1, 103, 0, 65, 0, 0, 0],
+        [169, 147, 130, 17, 96, 87, 143, 16, 138, 0, 0, 64, 125, 95, 0, 0],
+        [176, 179, 0, 0, 179, 179, 179, 77, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 180] = [
+        0, 1, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 7680, 8192, 8193,
+        16192, 30720, 32704, 32768, 131008, 262016, 2097152, 2359296, 6030336, 8323072, 10682368,
+        33554432, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204,
+        546307648, 805306369, 1073741824, 1073741916, 2113929216, 3221225472, 3758096384,
+        4026531840, 4160749568, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183,
+        47244640256, 51539615774, 51539619904, 51543810078, 51545914817, 66035122176, 412316860416,
+        412316862532, 412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488,
+        17303886364672, 36421322670080, 65128884076547, 65970697670631, 68168642985984,
+        70093866270720, 70368739983360, 136957967529984, 140737488355328, 263882790666240,
+        281470547525648, 281470682333183, 281474976710655, 281474976710656, 281474976710657,
+        281479271675905, 562675075514368, 562949953355776, 563001509683710, 844424930131968,
+        985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292,
+        4503599627370678, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336,
+        8760633772212225, 8989057312882695, 9042383626829823, 9851624185018758, 24822575045541890,
+        28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336,
+        58529202969772032, 72066390130950143, 112767012056334336, 143833713099145216,
+        189151184399892480, 216172782113783808, 220713756545974272, 288301294651703296,
+        302022650010533887, 504262420777140224, 558446353793941504, 572520102629474304,
+        593978171557150752, 1008806350890729472, 1009933895770046464, 1152921504606846976,
+        1152921504606846978, 1152921504606846982, 1153202979583561736, 1441151880758558727,
+        1715871458028158991, 1729382256910270467, 2301902359539744768, 2305843009196908767,
+        2305843009213693952, 2612078987781865472, 2771965570646540291, 3458764513820540928,
+        3731232291276455943, 4539628424389459968, 4589168020290535424, 4611404543450677248,
+        4611686018494513280, 4611686069967003678, 4671217976001691648, 6917775322003857411,
+        7421334051581067264, 8070450532247928832, 8788774672813524990, 9205357638345293827,
+        9222809086901354496, 9223091111633879040, 9223372036854775808, 9223372036854775935,
+        9223512774343131136, 9224216320050987008, 9224497932466651184, 9653465801268658176,
+        9727775195120332910, 10376293541461622786, 11526998316797657088, 11529215046068469760,
+        12103423998558208000, 12699025049277956096, 13005832773892571136, 13798747783286489088,
+        13832665517980123136, 13835058055282032640, 13835058055282163729, 13951307220663664640,
+        17870283321406128128, 17906312118425092095, 18158513697557839871, 18158513749097456062,
+        18374686479671623680, 18374686479671623682, 18444496122186563584, 18445618173802708992,
+        18446462598732840960, 18446462598733004800, 18446726481523507200, 18446744069414584320,
+        18446744069414584322, 18446744073575333888, 18446744073709027328, 18446744073709551615,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod cased {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (124, 6);
+    static BITSET_CHUNKS_MAP: [u8; 123] = [
+        13, 18, 0, 0, 12, 0, 0, 9, 14, 10, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 1, 2, 0, 16, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0,
+        0, 0, 0, 7,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 19] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 8, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 43, 62, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 10, 0, 50, 62, 58, 20],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 42, 44, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 31, 0, 62, 62, 62, 0, 62, 62, 62, 62, 54, 26, 27, 24],
+        [0, 0, 39, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 51, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 51, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 25],
+        [0, 22, 19, 37, 62, 62, 36, 61, 62, 62, 18, 12, 0, 30, 49, 38],
+        [0, 29, 9, 0, 34, 52, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [46, 55, 62, 17, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [62, 6, 42, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [62, 56, 33, 60, 28, 57, 62, 62, 62, 62, 48, 35, 40, 45, 47, 5],
+        [62, 62, 59, 62, 41, 53, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 63] = [
+        0, 15, 24, 511, 1023, 4087, 65535, 16253055, 134217726, 536805376, 1073741823, 4294967295,
+        133143986179, 4398046511103, 36009005809663, 70368744177663, 2251799813685247,
+        3509778554814463, 144115188074807295, 297241973452963840, 504403158265495676,
+        576460743713488896, 576460743847706622, 1152921504591118335, 2295745090394464220,
+        4557642822898941951, 4611686017001275199, 6908521828386340863, 8935141660164089791,
+        9223934986808197120, 13605092999309557792, 16717361816799216127, 16717361816799223999,
+        17005555242810474495, 17446871633794956420, 17870283321271910397, 17870283321406128127,
+        18410715276682199039, 18428729675200069631, 18428729675200069632, 18437736874452713471,
+        18446462598732840959, 18446462598732840960, 18446463698110251007, 18446466996779287551,
+        18446603336221163519, 18446603336221196287, 18446741874686295551, 18446743249075830783,
+        18446744056529672000, 18446744056529682432, 18446744069414584320, 18446744069414601696,
+        18446744069422972927, 18446744070475743231, 18446744071562067967, 18446744073707454463,
+        18446744073709419615, 18446744073709517055, 18446744073709550595, 18446744073709551599,
+        18446744073709551600, 18446744073709551615,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod cc {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (0, 0);
+    static BITSET_CHUNKS_MAP: [u8; 0] = [
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 1] = [
+        [1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 3] = [
+        0, 4294967295, 9223372036854775808,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod grapheme_extend {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 30);
+    static BITSET_CHUNKS_MAP: [u8; 123] = [
+        4, 15, 21, 27, 25, 3, 18, 23, 17, 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 2, 7, 10, 0, 8, 12, 29, 28, 24, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0,
+        11, 0, 9, 0, 20, 0, 13,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 31] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 18, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 70, 102, 29],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 62, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 83, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 35, 66, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 35, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 45, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 130, 78, 60, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 37, 0, 90, 0, 0],
+        [0, 0, 0, 0, 0, 129, 54, 0, 0, 3, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0],
+        [0, 0, 0, 19, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 67, 0, 114, 0, 137, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 7, 0, 0, 0, 125, 5, 24, 63, 0, 55, 135, 9, 64, 100],
+        [0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [10, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [12, 0, 48, 0, 92, 0, 0, 0, 25, 119, 113, 0, 96, 71, 53, 68],
+        [46, 0, 0, 116, 57, 17, 101, 44, 81, 94, 127, 80, 0, 0, 0, 52],
+        [49, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
+        [56, 26, 0, 136, 95, 43, 107, 105, 93, 79, 93, 132, 128, 42, 104, 20],
+        [59, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [85, 0, 0, 87, 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0],
+        [89, 0, 0, 0, 0, 0, 0, 38, 110, 27, 22, 0, 0, 0, 0, 0],
+        [109, 74, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0],
+        [124, 0, 82, 0, 123, 6, 21, 0, 0, 0, 0, 72, 0, 0, 0, 0],
+        [126, 40, 118, 39, 108, 41, 0, 34, 91, 14, 97, 13, 86, 112, 98, 4],
+        [133, 32, 120, 2, 0, 0, 122, 30, 121, 1, 84, 0, 51, 0, 0, 0],
+        [134, 115, 88, 0, 77, 69, 111, 11, 106, 0, 0, 50, 108, 76, 0, 0],
+        [137, 138, 0, 0, 138, 138, 138, 62, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 139] = [
+        0, 1, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 7680, 14336, 16128, 32640, 32768,
+        131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192,
+        159383552, 234881024, 243138688, 536879204, 537919040, 805306369, 1073741824, 1073741916,
+        1610612736, 2153546752, 3221225472, 3758096384, 4294967296, 4512022528, 51545911364,
+        51545914817, 51548004382, 51552198686, 51556262398, 137438953472, 412316860416,
+        412316862532, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672,
+        36421322670080, 65128884076547, 65970697670631, 67755789254656, 69200441769984,
+        70093866270720, 263882790666240, 277076930199552, 281470547525648, 281470681808895,
+        281474976710655, 281479271675904, 562675075514368, 562949953355776, 844424930131968,
+        985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292,
+        6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336, 8760633780600833,
+        8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234, 28848986089586688,
+        30958948903026688, 35747322042253312, 53805701016846336, 58529202969772032,
+        189151184399892480, 220713756545974272, 466122561432846339, 504262420777140224,
+        558446353793941504, 572520102629474304, 1009933895770046464, 1152921504606846982,
+        1152921504606851080, 1441151880758558727, 1724878657282899983, 2301902359539744768,
+        2305843009196908767, 2305843009213693952, 2310337812748042240, 3731232291276455943,
+        4589168020290535424, 4609293481125347328, 4611686018427387908, 4611686069975392286,
+        4671217976001691648, 5764607523034234882, 6341068275337658371, 7421334051581067264,
+        8788774672813524990, 9205357638345293827, 9222809086901354496, 9223090561878065152,
+        9223372036854775808, 9223372036854775935, 9224497932466651184, 9727775195120332910,
+        10376293541461622786, 11526998316797657088, 11959590285459062784, 12103423998558208000,
+        12699165786766311424, 13005832773892571136, 13798747783286489088, 13835058055282032640,
+        13835058055282163729, 13951307220663664640, 14987979559889010690, 17872468738205286400,
+        17906312118425092095, 18158513697557839871, 18158513749097456062, 18374686479671623680,
+        18374686479671623682, 18446462598732972032, 18446744056529158144, 18446744069414584320,
+        18446744073709551615,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod lowercase {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (122, 6);
+    static BITSET_CHUNKS_MAP: [u8; 118] = [
+        12, 16, 0, 0, 10, 0, 0, 11, 13, 8, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 2, 1, 0, 17, 0, 9, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 18] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 62, 71, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 9, 0, 50, 42, 44, 28],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35],
+        [0, 0, 3, 0, 71, 71, 71, 0, 46, 46, 48, 46, 24, 37, 38, 23],
+        [0, 29, 27, 57, 39, 51, 52, 43, 41, 70, 26, 11, 0, 34, 64, 32],
+        [0, 40, 8, 0, 33, 60, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [22, 13, 54, 66, 25, 15, 56, 63, 30, 19, 12, 55, 58, 61, 65, 4],
+        [59, 36, 46, 21, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [59, 49, 45, 47, 18, 69, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [67, 5, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 72] = [
+        0, 15, 16, 511, 3063, 65535, 16253055, 134217726, 536805376, 984263338, 4294967295,
+        133143986179, 274877905920, 1099509514240, 4398046445568, 17592185782272, 36009005809663,
+        46912496118442, 187649984473770, 281474972516352, 2251799813685247, 2339875276368554,
+        4503599560261632, 61925590106570972, 71777214282006783, 72057592964186127,
+        144115188074807295, 297241973452963840, 504403158265495560, 576460743713488896,
+        1152921487426978047, 1152921504590069760, 1814856824841797631, 3607524039012697088,
+        4362299189061746720, 4539628424389459968, 4601013482110844927, 4611405638684049471,
+        4674456033467236607, 6172933889249159850, 9223934986808197120, 10663022717737544362,
+        10808545280696953514, 12261519110656315968, 12294970652241842346, 12297829382473033730,
+        12297829382473034410, 12297829382473045332, 12297829382829550250, 12297829383904690175,
+        12298110845996498944, 15324248332066007893, 16596095761559859497, 16717361816799215616,
+        16987577794709946364, 17293822586148356092, 18158513701852807104, 18410715274543104000,
+        18428729675466407935, 18446462598732840960, 18446462598732858304, 18446462598737002495,
+        18446463698110251007, 18446673704966422527, 18446726481523572736, 18446739675663105535,
+        18446739675663106031, 18446742974197923840, 18446744056529682432, 18446744069414584320,
+        18446744073709529733, 18446744073709551615,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod n {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (124, 11);
+    static BITSET_CHUNKS_MAP: [u8; 124] = [
+        30, 7, 10, 24, 18, 3, 28, 20, 23, 27, 0, 15, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 2, 12, 17, 25, 16, 22, 19, 14, 21, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        4, 1, 0, 0, 9, 0, 13, 26,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 33] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 48],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 42, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 21, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 46, 0, 0, 0, 2],
+        [0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 30, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 30, 0, 44, 0, 30, 0, 30, 0, 40, 0, 33],
+        [0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 36, 43, 4, 0, 0, 0, 0, 51, 22, 3, 0, 12],
+        [0, 0, 0, 6, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 61, 46, 0, 0, 0, 0, 59, 0, 0, 23, 9, 0, 0],
+        [0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0],
+        [0, 14, 0, 14, 0, 0, 0, 0, 0, 14, 0, 2, 50, 0, 0, 0],
+        [0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 25, 0, 0, 0, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0, 10],
+        [0, 31, 0, 46, 64, 0, 0, 38, 0, 0, 0, 46, 0, 0, 0, 0],
+        [0, 45, 2, 0, 0, 70, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 58, 0, 30, 0, 41, 0, 30, 0, 14, 0, 14, 35, 0, 0, 0],
+        [0, 62, 29, 60, 17, 0, 54, 69, 0, 56, 19, 27, 0, 63, 28, 0],
+        [0, 65, 37, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 68, 18, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 8, 0],
+        [14, 0, 0, 0, 0, 7, 0, 16, 0, 0, 15, 0, 0, 14, 46, 0],
+        [39, 0, 0, 14, 2, 0, 0, 47, 0, 14, 0, 0, 0, 0, 0, 46],
+        [46, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [49, 0, 0, 0, 0, 0, 11, 0, 24, 20, 66, 0, 0, 0, 0, 0],
+        [72, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 73] = [
+        0, 999, 1023, 1026, 3072, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160, 4063232,
+        8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384, 4294901504,
+        17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296, 140737488355327,
+        272678883688448, 279275953455104, 280925220896768, 281200098803712, 281474976448512,
+        492581209243648, 2251524935778304, 2251795518717952, 4503595332403200, 4503599627370368,
+        8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024,
+        144114915328655360, 144115183780888576, 144115188075855871, 284007976623144960,
+        284008251501051904, 287948901175001088, 287948901242044416, 287953294926544896,
+        504407547722072192, 1152640029630136320, 1152921496016912384, 2305840810190438400,
+        2305843009213693952, 3458764513820540928, 4611615649683210238, 6917529027641082367,
+        8217943420044312576, 9151595642915651584, 9223372032559808512, 17870283321406128128,
+        18158513697557839872, 18302628889911885824, 18374686483949813760, 18428729675200069632,
+        18446181123756130304, 18446181123756131327, 18446739675663040512, 18446744069414584320,
+        18446744073709355007, 18446744073709486080, 18446744073709535232, 18446744073709551615,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod uppercase {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (124, 6);
+    static BITSET_CHUNKS_MAP: [u8; 123] = [
+        12, 15, 0, 0, 11, 0, 0, 8, 5, 9, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 1, 0, 13, 0, 7, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0,
+        0, 0, 4,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 10, 0, 38, 46, 44, 2],
+        [0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 51, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 60, 62, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 23, 34, 35],
+        [0, 0, 57, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 66, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30],
+        [0, 11, 0, 12, 50, 37, 36, 45, 47, 6, 0, 0, 0, 49, 18, 53],
+        [15, 0, 60, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [22, 52, 43, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [25, 39, 42, 41, 59, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [58, 65, 29, 17, 48, 63, 31, 20, 55, 61, 64, 32, 28, 21, 16, 4],
+    ];
+    static BITSET: [u64; 67] = [
+        0, 8, 116, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726,
+        2139095039, 4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568,
+        17575006099264, 23456248059221, 70368743129088, 140737484161024, 140737488355327,
+        280378317225728, 281470681743392, 281474976710655, 1169903278445909, 2251799813685247,
+        9007198986305536, 17977448100528131, 18014398509481983, 288230371856744511,
+        576460735123554305, 576460743713488896, 1080863910568919040, 1080897995681042176,
+        1274187559846268630, 3122495741643543722, 6148633210533183488, 6148914689804861440,
+        6148914690880001365, 6148914691236506283, 6148914691236516865, 6148914691236517205,
+        6151773421467674709, 6184099063146390672, 7638198793012598101, 7783721355972007253,
+        8863084067199903664, 9242793810247811072, 12273810184460391765, 13839347594782259332,
+        13845730589451223040, 16613872850358272000, 16717361816799215616, 17293822586282573568,
+        18374966856193736448, 18428729675200069632, 18442240474149289983, 18446274948748367189,
+        18446462598732840960, 18446462598737035263, 18446466996779287551, 18446726481523637343,
+        18446742974197924863, 18446742974197940223, 18446744069414584320,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod white_space {
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (12, 2);
+    static BITSET_CHUNKS_MAP: [u8; 9] = [
+        3, 0, 0, 0, 0, 1, 0, 0, 4,
+    ];
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 5] = [
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
+        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+    ];
+    static BITSET: [u64; 6] = [
+        0, 1, 2147483648, 4294967328, 4294983168, 144036023240703,
+    ];
+
+    pub fn lookup(c: char) -> bool {
+        super::range_search(
+            c as u32,
+            &BITSET_CHUNKS_MAP,
+            BITSET_LAST_CHUNK_MAP,
+            &BITSET_INDEX_CHUNKS,
+            &BITSET,
+        )
+    }
+}
+
+#[rustfmt::skip]
+pub mod conversions {
+    pub fn to_lower(c: char) -> [char; 3] {
+        match bsearch_case_table(c, LOWERCASE_TABLE) {
+            None => [c, '\0', '\0'],
+            Some(index) => LOWERCASE_TABLE[index].1,
+        }
+    }
+
+    pub fn to_upper(c: char) -> [char; 3] {
+        match bsearch_case_table(c, UPPERCASE_TABLE) {
+            None => [c, '\0', '\0'],
+            Some(index) => UPPERCASE_TABLE[index].1,
+        }
+    }
+
+    fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
+        table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
+    }
+    static LOWERCASE_TABLE: &[(char, [char; 3])] = &[
+        ('A', ['a', '\u{0}', '\u{0}']), ('B', ['b', '\u{0}', '\u{0}']),
+        ('C', ['c', '\u{0}', '\u{0}']), ('D', ['d', '\u{0}', '\u{0}']),
+        ('E', ['e', '\u{0}', '\u{0}']), ('F', ['f', '\u{0}', '\u{0}']),
+        ('G', ['g', '\u{0}', '\u{0}']), ('H', ['h', '\u{0}', '\u{0}']),
+        ('I', ['i', '\u{0}', '\u{0}']), ('J', ['j', '\u{0}', '\u{0}']),
+        ('K', ['k', '\u{0}', '\u{0}']), ('L', ['l', '\u{0}', '\u{0}']),
+        ('M', ['m', '\u{0}', '\u{0}']), ('N', ['n', '\u{0}', '\u{0}']),
+        ('O', ['o', '\u{0}', '\u{0}']), ('P', ['p', '\u{0}', '\u{0}']),
+        ('Q', ['q', '\u{0}', '\u{0}']), ('R', ['r', '\u{0}', '\u{0}']),
+        ('S', ['s', '\u{0}', '\u{0}']), ('T', ['t', '\u{0}', '\u{0}']),
+        ('U', ['u', '\u{0}', '\u{0}']), ('V', ['v', '\u{0}', '\u{0}']),
+        ('W', ['w', '\u{0}', '\u{0}']), ('X', ['x', '\u{0}', '\u{0}']),
+        ('Y', ['y', '\u{0}', '\u{0}']), ('Z', ['z', '\u{0}', '\u{0}']),
+        ('\u{c0}', ['\u{e0}', '\u{0}', '\u{0}']), ('\u{c1}', ['\u{e1}', '\u{0}', '\u{0}']),
+        ('\u{c2}', ['\u{e2}', '\u{0}', '\u{0}']), ('\u{c3}', ['\u{e3}', '\u{0}', '\u{0}']),
+        ('\u{c4}', ['\u{e4}', '\u{0}', '\u{0}']), ('\u{c5}', ['\u{e5}', '\u{0}', '\u{0}']),
+        ('\u{c6}', ['\u{e6}', '\u{0}', '\u{0}']), ('\u{c7}', ['\u{e7}', '\u{0}', '\u{0}']),
+        ('\u{c8}', ['\u{e8}', '\u{0}', '\u{0}']), ('\u{c9}', ['\u{e9}', '\u{0}', '\u{0}']),
+        ('\u{ca}', ['\u{ea}', '\u{0}', '\u{0}']), ('\u{cb}', ['\u{eb}', '\u{0}', '\u{0}']),
+        ('\u{cc}', ['\u{ec}', '\u{0}', '\u{0}']), ('\u{cd}', ['\u{ed}', '\u{0}', '\u{0}']),
+        ('\u{ce}', ['\u{ee}', '\u{0}', '\u{0}']), ('\u{cf}', ['\u{ef}', '\u{0}', '\u{0}']),
+        ('\u{d0}', ['\u{f0}', '\u{0}', '\u{0}']), ('\u{d1}', ['\u{f1}', '\u{0}', '\u{0}']),
+        ('\u{d2}', ['\u{f2}', '\u{0}', '\u{0}']), ('\u{d3}', ['\u{f3}', '\u{0}', '\u{0}']),
+        ('\u{d4}', ['\u{f4}', '\u{0}', '\u{0}']), ('\u{d5}', ['\u{f5}', '\u{0}', '\u{0}']),
+        ('\u{d6}', ['\u{f6}', '\u{0}', '\u{0}']), ('\u{d8}', ['\u{f8}', '\u{0}', '\u{0}']),
+        ('\u{d9}', ['\u{f9}', '\u{0}', '\u{0}']), ('\u{da}', ['\u{fa}', '\u{0}', '\u{0}']),
+        ('\u{db}', ['\u{fb}', '\u{0}', '\u{0}']), ('\u{dc}', ['\u{fc}', '\u{0}', '\u{0}']),
+        ('\u{dd}', ['\u{fd}', '\u{0}', '\u{0}']), ('\u{de}', ['\u{fe}', '\u{0}', '\u{0}']),
+        ('\u{100}', ['\u{101}', '\u{0}', '\u{0}']), ('\u{102}', ['\u{103}', '\u{0}', '\u{0}']),
+        ('\u{104}', ['\u{105}', '\u{0}', '\u{0}']), ('\u{106}', ['\u{107}', '\u{0}', '\u{0}']),
+        ('\u{108}', ['\u{109}', '\u{0}', '\u{0}']), ('\u{10a}', ['\u{10b}', '\u{0}', '\u{0}']),
+        ('\u{10c}', ['\u{10d}', '\u{0}', '\u{0}']), ('\u{10e}', ['\u{10f}', '\u{0}', '\u{0}']),
+        ('\u{110}', ['\u{111}', '\u{0}', '\u{0}']), ('\u{112}', ['\u{113}', '\u{0}', '\u{0}']),
+        ('\u{114}', ['\u{115}', '\u{0}', '\u{0}']), ('\u{116}', ['\u{117}', '\u{0}', '\u{0}']),
+        ('\u{118}', ['\u{119}', '\u{0}', '\u{0}']), ('\u{11a}', ['\u{11b}', '\u{0}', '\u{0}']),
+        ('\u{11c}', ['\u{11d}', '\u{0}', '\u{0}']), ('\u{11e}', ['\u{11f}', '\u{0}', '\u{0}']),
+        ('\u{120}', ['\u{121}', '\u{0}', '\u{0}']), ('\u{122}', ['\u{123}', '\u{0}', '\u{0}']),
+        ('\u{124}', ['\u{125}', '\u{0}', '\u{0}']), ('\u{126}', ['\u{127}', '\u{0}', '\u{0}']),
+        ('\u{128}', ['\u{129}', '\u{0}', '\u{0}']), ('\u{12a}', ['\u{12b}', '\u{0}', '\u{0}']),
+        ('\u{12c}', ['\u{12d}', '\u{0}', '\u{0}']), ('\u{12e}', ['\u{12f}', '\u{0}', '\u{0}']),
+        ('\u{130}', ['i', '\u{307}', '\u{0}']), ('\u{132}', ['\u{133}', '\u{0}', '\u{0}']),
+        ('\u{134}', ['\u{135}', '\u{0}', '\u{0}']), ('\u{136}', ['\u{137}', '\u{0}', '\u{0}']),
+        ('\u{139}', ['\u{13a}', '\u{0}', '\u{0}']), ('\u{13b}', ['\u{13c}', '\u{0}', '\u{0}']),
+        ('\u{13d}', ['\u{13e}', '\u{0}', '\u{0}']), ('\u{13f}', ['\u{140}', '\u{0}', '\u{0}']),
+        ('\u{141}', ['\u{142}', '\u{0}', '\u{0}']), ('\u{143}', ['\u{144}', '\u{0}', '\u{0}']),
+        ('\u{145}', ['\u{146}', '\u{0}', '\u{0}']), ('\u{147}', ['\u{148}', '\u{0}', '\u{0}']),
+        ('\u{14a}', ['\u{14b}', '\u{0}', '\u{0}']), ('\u{14c}', ['\u{14d}', '\u{0}', '\u{0}']),
+        ('\u{14e}', ['\u{14f}', '\u{0}', '\u{0}']), ('\u{150}', ['\u{151}', '\u{0}', '\u{0}']),
+        ('\u{152}', ['\u{153}', '\u{0}', '\u{0}']), ('\u{154}', ['\u{155}', '\u{0}', '\u{0}']),
+        ('\u{156}', ['\u{157}', '\u{0}', '\u{0}']), ('\u{158}', ['\u{159}', '\u{0}', '\u{0}']),
+        ('\u{15a}', ['\u{15b}', '\u{0}', '\u{0}']), ('\u{15c}', ['\u{15d}', '\u{0}', '\u{0}']),
+        ('\u{15e}', ['\u{15f}', '\u{0}', '\u{0}']), ('\u{160}', ['\u{161}', '\u{0}', '\u{0}']),
+        ('\u{162}', ['\u{163}', '\u{0}', '\u{0}']), ('\u{164}', ['\u{165}', '\u{0}', '\u{0}']),
+        ('\u{166}', ['\u{167}', '\u{0}', '\u{0}']), ('\u{168}', ['\u{169}', '\u{0}', '\u{0}']),
+        ('\u{16a}', ['\u{16b}', '\u{0}', '\u{0}']), ('\u{16c}', ['\u{16d}', '\u{0}', '\u{0}']),
+        ('\u{16e}', ['\u{16f}', '\u{0}', '\u{0}']), ('\u{170}', ['\u{171}', '\u{0}', '\u{0}']),
+        ('\u{172}', ['\u{173}', '\u{0}', '\u{0}']), ('\u{174}', ['\u{175}', '\u{0}', '\u{0}']),
+        ('\u{176}', ['\u{177}', '\u{0}', '\u{0}']), ('\u{178}', ['\u{ff}', '\u{0}', '\u{0}']),
+        ('\u{179}', ['\u{17a}', '\u{0}', '\u{0}']), ('\u{17b}', ['\u{17c}', '\u{0}', '\u{0}']),
+        ('\u{17d}', ['\u{17e}', '\u{0}', '\u{0}']), ('\u{181}', ['\u{253}', '\u{0}', '\u{0}']),
+        ('\u{182}', ['\u{183}', '\u{0}', '\u{0}']), ('\u{184}', ['\u{185}', '\u{0}', '\u{0}']),
+        ('\u{186}', ['\u{254}', '\u{0}', '\u{0}']), ('\u{187}', ['\u{188}', '\u{0}', '\u{0}']),
+        ('\u{189}', ['\u{256}', '\u{0}', '\u{0}']), ('\u{18a}', ['\u{257}', '\u{0}', '\u{0}']),
+        ('\u{18b}', ['\u{18c}', '\u{0}', '\u{0}']), ('\u{18e}', ['\u{1dd}', '\u{0}', '\u{0}']),
+        ('\u{18f}', ['\u{259}', '\u{0}', '\u{0}']), ('\u{190}', ['\u{25b}', '\u{0}', '\u{0}']),
+        ('\u{191}', ['\u{192}', '\u{0}', '\u{0}']), ('\u{193}', ['\u{260}', '\u{0}', '\u{0}']),
+        ('\u{194}', ['\u{263}', '\u{0}', '\u{0}']), ('\u{196}', ['\u{269}', '\u{0}', '\u{0}']),
+        ('\u{197}', ['\u{268}', '\u{0}', '\u{0}']), ('\u{198}', ['\u{199}', '\u{0}', '\u{0}']),
+        ('\u{19c}', ['\u{26f}', '\u{0}', '\u{0}']), ('\u{19d}', ['\u{272}', '\u{0}', '\u{0}']),
+        ('\u{19f}', ['\u{275}', '\u{0}', '\u{0}']), ('\u{1a0}', ['\u{1a1}', '\u{0}', '\u{0}']),
+        ('\u{1a2}', ['\u{1a3}', '\u{0}', '\u{0}']), ('\u{1a4}', ['\u{1a5}', '\u{0}', '\u{0}']),
+        ('\u{1a6}', ['\u{280}', '\u{0}', '\u{0}']), ('\u{1a7}', ['\u{1a8}', '\u{0}', '\u{0}']),
+        ('\u{1a9}', ['\u{283}', '\u{0}', '\u{0}']), ('\u{1ac}', ['\u{1ad}', '\u{0}', '\u{0}']),
+        ('\u{1ae}', ['\u{288}', '\u{0}', '\u{0}']), ('\u{1af}', ['\u{1b0}', '\u{0}', '\u{0}']),
+        ('\u{1b1}', ['\u{28a}', '\u{0}', '\u{0}']), ('\u{1b2}', ['\u{28b}', '\u{0}', '\u{0}']),
+        ('\u{1b3}', ['\u{1b4}', '\u{0}', '\u{0}']), ('\u{1b5}', ['\u{1b6}', '\u{0}', '\u{0}']),
+        ('\u{1b7}', ['\u{292}', '\u{0}', '\u{0}']), ('\u{1b8}', ['\u{1b9}', '\u{0}', '\u{0}']),
+        ('\u{1bc}', ['\u{1bd}', '\u{0}', '\u{0}']), ('\u{1c4}', ['\u{1c6}', '\u{0}', '\u{0}']),
+        ('\u{1c5}', ['\u{1c6}', '\u{0}', '\u{0}']), ('\u{1c7}', ['\u{1c9}', '\u{0}', '\u{0}']),
+        ('\u{1c8}', ['\u{1c9}', '\u{0}', '\u{0}']), ('\u{1ca}', ['\u{1cc}', '\u{0}', '\u{0}']),
+        ('\u{1cb}', ['\u{1cc}', '\u{0}', '\u{0}']), ('\u{1cd}', ['\u{1ce}', '\u{0}', '\u{0}']),
+        ('\u{1cf}', ['\u{1d0}', '\u{0}', '\u{0}']), ('\u{1d1}', ['\u{1d2}', '\u{0}', '\u{0}']),
+        ('\u{1d3}', ['\u{1d4}', '\u{0}', '\u{0}']), ('\u{1d5}', ['\u{1d6}', '\u{0}', '\u{0}']),
+        ('\u{1d7}', ['\u{1d8}', '\u{0}', '\u{0}']), ('\u{1d9}', ['\u{1da}', '\u{0}', '\u{0}']),
+        ('\u{1db}', ['\u{1dc}', '\u{0}', '\u{0}']), ('\u{1de}', ['\u{1df}', '\u{0}', '\u{0}']),
+        ('\u{1e0}', ['\u{1e1}', '\u{0}', '\u{0}']), ('\u{1e2}', ['\u{1e3}', '\u{0}', '\u{0}']),
+        ('\u{1e4}', ['\u{1e5}', '\u{0}', '\u{0}']), ('\u{1e6}', ['\u{1e7}', '\u{0}', '\u{0}']),
+        ('\u{1e8}', ['\u{1e9}', '\u{0}', '\u{0}']), ('\u{1ea}', ['\u{1eb}', '\u{0}', '\u{0}']),
+        ('\u{1ec}', ['\u{1ed}', '\u{0}', '\u{0}']), ('\u{1ee}', ['\u{1ef}', '\u{0}', '\u{0}']),
+        ('\u{1f1}', ['\u{1f3}', '\u{0}', '\u{0}']), ('\u{1f2}', ['\u{1f3}', '\u{0}', '\u{0}']),
+        ('\u{1f4}', ['\u{1f5}', '\u{0}', '\u{0}']), ('\u{1f6}', ['\u{195}', '\u{0}', '\u{0}']),
+        ('\u{1f7}', ['\u{1bf}', '\u{0}', '\u{0}']), ('\u{1f8}', ['\u{1f9}', '\u{0}', '\u{0}']),
+        ('\u{1fa}', ['\u{1fb}', '\u{0}', '\u{0}']), ('\u{1fc}', ['\u{1fd}', '\u{0}', '\u{0}']),
+        ('\u{1fe}', ['\u{1ff}', '\u{0}', '\u{0}']), ('\u{200}', ['\u{201}', '\u{0}', '\u{0}']),
+        ('\u{202}', ['\u{203}', '\u{0}', '\u{0}']), ('\u{204}', ['\u{205}', '\u{0}', '\u{0}']),
+        ('\u{206}', ['\u{207}', '\u{0}', '\u{0}']), ('\u{208}', ['\u{209}', '\u{0}', '\u{0}']),
+        ('\u{20a}', ['\u{20b}', '\u{0}', '\u{0}']), ('\u{20c}', ['\u{20d}', '\u{0}', '\u{0}']),
+        ('\u{20e}', ['\u{20f}', '\u{0}', '\u{0}']), ('\u{210}', ['\u{211}', '\u{0}', '\u{0}']),
+        ('\u{212}', ['\u{213}', '\u{0}', '\u{0}']), ('\u{214}', ['\u{215}', '\u{0}', '\u{0}']),
+        ('\u{216}', ['\u{217}', '\u{0}', '\u{0}']), ('\u{218}', ['\u{219}', '\u{0}', '\u{0}']),
+        ('\u{21a}', ['\u{21b}', '\u{0}', '\u{0}']), ('\u{21c}', ['\u{21d}', '\u{0}', '\u{0}']),
+        ('\u{21e}', ['\u{21f}', '\u{0}', '\u{0}']), ('\u{220}', ['\u{19e}', '\u{0}', '\u{0}']),
+        ('\u{222}', ['\u{223}', '\u{0}', '\u{0}']), ('\u{224}', ['\u{225}', '\u{0}', '\u{0}']),
+        ('\u{226}', ['\u{227}', '\u{0}', '\u{0}']), ('\u{228}', ['\u{229}', '\u{0}', '\u{0}']),
+        ('\u{22a}', ['\u{22b}', '\u{0}', '\u{0}']), ('\u{22c}', ['\u{22d}', '\u{0}', '\u{0}']),
+        ('\u{22e}', ['\u{22f}', '\u{0}', '\u{0}']), ('\u{230}', ['\u{231}', '\u{0}', '\u{0}']),
+        ('\u{232}', ['\u{233}', '\u{0}', '\u{0}']), ('\u{23a}', ['\u{2c65}', '\u{0}', '\u{0}']),
+        ('\u{23b}', ['\u{23c}', '\u{0}', '\u{0}']), ('\u{23d}', ['\u{19a}', '\u{0}', '\u{0}']),
+        ('\u{23e}', ['\u{2c66}', '\u{0}', '\u{0}']), ('\u{241}', ['\u{242}', '\u{0}', '\u{0}']),
+        ('\u{243}', ['\u{180}', '\u{0}', '\u{0}']), ('\u{244}', ['\u{289}', '\u{0}', '\u{0}']),
+        ('\u{245}', ['\u{28c}', '\u{0}', '\u{0}']), ('\u{246}', ['\u{247}', '\u{0}', '\u{0}']),
+        ('\u{248}', ['\u{249}', '\u{0}', '\u{0}']), ('\u{24a}', ['\u{24b}', '\u{0}', '\u{0}']),
+        ('\u{24c}', ['\u{24d}', '\u{0}', '\u{0}']), ('\u{24e}', ['\u{24f}', '\u{0}', '\u{0}']),
+        ('\u{370}', ['\u{371}', '\u{0}', '\u{0}']), ('\u{372}', ['\u{373}', '\u{0}', '\u{0}']),
+        ('\u{376}', ['\u{377}', '\u{0}', '\u{0}']), ('\u{37f}', ['\u{3f3}', '\u{0}', '\u{0}']),
+        ('\u{386}', ['\u{3ac}', '\u{0}', '\u{0}']), ('\u{388}', ['\u{3ad}', '\u{0}', '\u{0}']),
+        ('\u{389}', ['\u{3ae}', '\u{0}', '\u{0}']), ('\u{38a}', ['\u{3af}', '\u{0}', '\u{0}']),
+        ('\u{38c}', ['\u{3cc}', '\u{0}', '\u{0}']), ('\u{38e}', ['\u{3cd}', '\u{0}', '\u{0}']),
+        ('\u{38f}', ['\u{3ce}', '\u{0}', '\u{0}']), ('\u{391}', ['\u{3b1}', '\u{0}', '\u{0}']),
+        ('\u{392}', ['\u{3b2}', '\u{0}', '\u{0}']), ('\u{393}', ['\u{3b3}', '\u{0}', '\u{0}']),
+        ('\u{394}', ['\u{3b4}', '\u{0}', '\u{0}']), ('\u{395}', ['\u{3b5}', '\u{0}', '\u{0}']),
+        ('\u{396}', ['\u{3b6}', '\u{0}', '\u{0}']), ('\u{397}', ['\u{3b7}', '\u{0}', '\u{0}']),
+        ('\u{398}', ['\u{3b8}', '\u{0}', '\u{0}']), ('\u{399}', ['\u{3b9}', '\u{0}', '\u{0}']),
+        ('\u{39a}', ['\u{3ba}', '\u{0}', '\u{0}']), ('\u{39b}', ['\u{3bb}', '\u{0}', '\u{0}']),
+        ('\u{39c}', ['\u{3bc}', '\u{0}', '\u{0}']), ('\u{39d}', ['\u{3bd}', '\u{0}', '\u{0}']),
+        ('\u{39e}', ['\u{3be}', '\u{0}', '\u{0}']), ('\u{39f}', ['\u{3bf}', '\u{0}', '\u{0}']),
+        ('\u{3a0}', ['\u{3c0}', '\u{0}', '\u{0}']), ('\u{3a1}', ['\u{3c1}', '\u{0}', '\u{0}']),
+        ('\u{3a3}', ['\u{3c3}', '\u{0}', '\u{0}']), ('\u{3a4}', ['\u{3c4}', '\u{0}', '\u{0}']),
+        ('\u{3a5}', ['\u{3c5}', '\u{0}', '\u{0}']), ('\u{3a6}', ['\u{3c6}', '\u{0}', '\u{0}']),
+        ('\u{3a7}', ['\u{3c7}', '\u{0}', '\u{0}']), ('\u{3a8}', ['\u{3c8}', '\u{0}', '\u{0}']),
+        ('\u{3a9}', ['\u{3c9}', '\u{0}', '\u{0}']), ('\u{3aa}', ['\u{3ca}', '\u{0}', '\u{0}']),
+        ('\u{3ab}', ['\u{3cb}', '\u{0}', '\u{0}']), ('\u{3cf}', ['\u{3d7}', '\u{0}', '\u{0}']),
+        ('\u{3d8}', ['\u{3d9}', '\u{0}', '\u{0}']), ('\u{3da}', ['\u{3db}', '\u{0}', '\u{0}']),
+        ('\u{3dc}', ['\u{3dd}', '\u{0}', '\u{0}']), ('\u{3de}', ['\u{3df}', '\u{0}', '\u{0}']),
+        ('\u{3e0}', ['\u{3e1}', '\u{0}', '\u{0}']), ('\u{3e2}', ['\u{3e3}', '\u{0}', '\u{0}']),
+        ('\u{3e4}', ['\u{3e5}', '\u{0}', '\u{0}']), ('\u{3e6}', ['\u{3e7}', '\u{0}', '\u{0}']),
+        ('\u{3e8}', ['\u{3e9}', '\u{0}', '\u{0}']), ('\u{3ea}', ['\u{3eb}', '\u{0}', '\u{0}']),
+        ('\u{3ec}', ['\u{3ed}', '\u{0}', '\u{0}']), ('\u{3ee}', ['\u{3ef}', '\u{0}', '\u{0}']),
+        ('\u{3f4}', ['\u{3b8}', '\u{0}', '\u{0}']), ('\u{3f7}', ['\u{3f8}', '\u{0}', '\u{0}']),
+        ('\u{3f9}', ['\u{3f2}', '\u{0}', '\u{0}']), ('\u{3fa}', ['\u{3fb}', '\u{0}', '\u{0}']),
+        ('\u{3fd}', ['\u{37b}', '\u{0}', '\u{0}']), ('\u{3fe}', ['\u{37c}', '\u{0}', '\u{0}']),
+        ('\u{3ff}', ['\u{37d}', '\u{0}', '\u{0}']), ('\u{400}', ['\u{450}', '\u{0}', '\u{0}']),
+        ('\u{401}', ['\u{451}', '\u{0}', '\u{0}']), ('\u{402}', ['\u{452}', '\u{0}', '\u{0}']),
+        ('\u{403}', ['\u{453}', '\u{0}', '\u{0}']), ('\u{404}', ['\u{454}', '\u{0}', '\u{0}']),
+        ('\u{405}', ['\u{455}', '\u{0}', '\u{0}']), ('\u{406}', ['\u{456}', '\u{0}', '\u{0}']),
+        ('\u{407}', ['\u{457}', '\u{0}', '\u{0}']), ('\u{408}', ['\u{458}', '\u{0}', '\u{0}']),
+        ('\u{409}', ['\u{459}', '\u{0}', '\u{0}']), ('\u{40a}', ['\u{45a}', '\u{0}', '\u{0}']),
+        ('\u{40b}', ['\u{45b}', '\u{0}', '\u{0}']), ('\u{40c}', ['\u{45c}', '\u{0}', '\u{0}']),
+        ('\u{40d}', ['\u{45d}', '\u{0}', '\u{0}']), ('\u{40e}', ['\u{45e}', '\u{0}', '\u{0}']),
+        ('\u{40f}', ['\u{45f}', '\u{0}', '\u{0}']), ('\u{410}', ['\u{430}', '\u{0}', '\u{0}']),
+        ('\u{411}', ['\u{431}', '\u{0}', '\u{0}']), ('\u{412}', ['\u{432}', '\u{0}', '\u{0}']),
+        ('\u{413}', ['\u{433}', '\u{0}', '\u{0}']), ('\u{414}', ['\u{434}', '\u{0}', '\u{0}']),
+        ('\u{415}', ['\u{435}', '\u{0}', '\u{0}']), ('\u{416}', ['\u{436}', '\u{0}', '\u{0}']),
+        ('\u{417}', ['\u{437}', '\u{0}', '\u{0}']), ('\u{418}', ['\u{438}', '\u{0}', '\u{0}']),
+        ('\u{419}', ['\u{439}', '\u{0}', '\u{0}']), ('\u{41a}', ['\u{43a}', '\u{0}', '\u{0}']),
+        ('\u{41b}', ['\u{43b}', '\u{0}', '\u{0}']), ('\u{41c}', ['\u{43c}', '\u{0}', '\u{0}']),
+        ('\u{41d}', ['\u{43d}', '\u{0}', '\u{0}']), ('\u{41e}', ['\u{43e}', '\u{0}', '\u{0}']),
+        ('\u{41f}', ['\u{43f}', '\u{0}', '\u{0}']), ('\u{420}', ['\u{440}', '\u{0}', '\u{0}']),
+        ('\u{421}', ['\u{441}', '\u{0}', '\u{0}']), ('\u{422}', ['\u{442}', '\u{0}', '\u{0}']),
+        ('\u{423}', ['\u{443}', '\u{0}', '\u{0}']), ('\u{424}', ['\u{444}', '\u{0}', '\u{0}']),
+        ('\u{425}', ['\u{445}', '\u{0}', '\u{0}']), ('\u{426}', ['\u{446}', '\u{0}', '\u{0}']),
+        ('\u{427}', ['\u{447}', '\u{0}', '\u{0}']), ('\u{428}', ['\u{448}', '\u{0}', '\u{0}']),
+        ('\u{429}', ['\u{449}', '\u{0}', '\u{0}']), ('\u{42a}', ['\u{44a}', '\u{0}', '\u{0}']),
+        ('\u{42b}', ['\u{44b}', '\u{0}', '\u{0}']), ('\u{42c}', ['\u{44c}', '\u{0}', '\u{0}']),
+        ('\u{42d}', ['\u{44d}', '\u{0}', '\u{0}']), ('\u{42e}', ['\u{44e}', '\u{0}', '\u{0}']),
+        ('\u{42f}', ['\u{44f}', '\u{0}', '\u{0}']), ('\u{460}', ['\u{461}', '\u{0}', '\u{0}']),
+        ('\u{462}', ['\u{463}', '\u{0}', '\u{0}']), ('\u{464}', ['\u{465}', '\u{0}', '\u{0}']),
+        ('\u{466}', ['\u{467}', '\u{0}', '\u{0}']), ('\u{468}', ['\u{469}', '\u{0}', '\u{0}']),
+        ('\u{46a}', ['\u{46b}', '\u{0}', '\u{0}']), ('\u{46c}', ['\u{46d}', '\u{0}', '\u{0}']),
+        ('\u{46e}', ['\u{46f}', '\u{0}', '\u{0}']), ('\u{470}', ['\u{471}', '\u{0}', '\u{0}']),
+        ('\u{472}', ['\u{473}', '\u{0}', '\u{0}']), ('\u{474}', ['\u{475}', '\u{0}', '\u{0}']),
+        ('\u{476}', ['\u{477}', '\u{0}', '\u{0}']), ('\u{478}', ['\u{479}', '\u{0}', '\u{0}']),
+        ('\u{47a}', ['\u{47b}', '\u{0}', '\u{0}']), ('\u{47c}', ['\u{47d}', '\u{0}', '\u{0}']),
+        ('\u{47e}', ['\u{47f}', '\u{0}', '\u{0}']), ('\u{480}', ['\u{481}', '\u{0}', '\u{0}']),
+        ('\u{48a}', ['\u{48b}', '\u{0}', '\u{0}']), ('\u{48c}', ['\u{48d}', '\u{0}', '\u{0}']),
+        ('\u{48e}', ['\u{48f}', '\u{0}', '\u{0}']), ('\u{490}', ['\u{491}', '\u{0}', '\u{0}']),
+        ('\u{492}', ['\u{493}', '\u{0}', '\u{0}']), ('\u{494}', ['\u{495}', '\u{0}', '\u{0}']),
+        ('\u{496}', ['\u{497}', '\u{0}', '\u{0}']), ('\u{498}', ['\u{499}', '\u{0}', '\u{0}']),
+        ('\u{49a}', ['\u{49b}', '\u{0}', '\u{0}']), ('\u{49c}', ['\u{49d}', '\u{0}', '\u{0}']),
+        ('\u{49e}', ['\u{49f}', '\u{0}', '\u{0}']), ('\u{4a0}', ['\u{4a1}', '\u{0}', '\u{0}']),
+        ('\u{4a2}', ['\u{4a3}', '\u{0}', '\u{0}']), ('\u{4a4}', ['\u{4a5}', '\u{0}', '\u{0}']),
+        ('\u{4a6}', ['\u{4a7}', '\u{0}', '\u{0}']), ('\u{4a8}', ['\u{4a9}', '\u{0}', '\u{0}']),
+        ('\u{4aa}', ['\u{4ab}', '\u{0}', '\u{0}']), ('\u{4ac}', ['\u{4ad}', '\u{0}', '\u{0}']),
+        ('\u{4ae}', ['\u{4af}', '\u{0}', '\u{0}']), ('\u{4b0}', ['\u{4b1}', '\u{0}', '\u{0}']),
+        ('\u{4b2}', ['\u{4b3}', '\u{0}', '\u{0}']), ('\u{4b4}', ['\u{4b5}', '\u{0}', '\u{0}']),
+        ('\u{4b6}', ['\u{4b7}', '\u{0}', '\u{0}']), ('\u{4b8}', ['\u{4b9}', '\u{0}', '\u{0}']),
+        ('\u{4ba}', ['\u{4bb}', '\u{0}', '\u{0}']), ('\u{4bc}', ['\u{4bd}', '\u{0}', '\u{0}']),
+        ('\u{4be}', ['\u{4bf}', '\u{0}', '\u{0}']), ('\u{4c0}', ['\u{4cf}', '\u{0}', '\u{0}']),
+        ('\u{4c1}', ['\u{4c2}', '\u{0}', '\u{0}']), ('\u{4c3}', ['\u{4c4}', '\u{0}', '\u{0}']),
+        ('\u{4c5}', ['\u{4c6}', '\u{0}', '\u{0}']), ('\u{4c7}', ['\u{4c8}', '\u{0}', '\u{0}']),
+        ('\u{4c9}', ['\u{4ca}', '\u{0}', '\u{0}']), ('\u{4cb}', ['\u{4cc}', '\u{0}', '\u{0}']),
+        ('\u{4cd}', ['\u{4ce}', '\u{0}', '\u{0}']), ('\u{4d0}', ['\u{4d1}', '\u{0}', '\u{0}']),
+        ('\u{4d2}', ['\u{4d3}', '\u{0}', '\u{0}']), ('\u{4d4}', ['\u{4d5}', '\u{0}', '\u{0}']),
+        ('\u{4d6}', ['\u{4d7}', '\u{0}', '\u{0}']), ('\u{4d8}', ['\u{4d9}', '\u{0}', '\u{0}']),
+        ('\u{4da}', ['\u{4db}', '\u{0}', '\u{0}']), ('\u{4dc}', ['\u{4dd}', '\u{0}', '\u{0}']),
+        ('\u{4de}', ['\u{4df}', '\u{0}', '\u{0}']), ('\u{4e0}', ['\u{4e1}', '\u{0}', '\u{0}']),
+        ('\u{4e2}', ['\u{4e3}', '\u{0}', '\u{0}']), ('\u{4e4}', ['\u{4e5}', '\u{0}', '\u{0}']),
+        ('\u{4e6}', ['\u{4e7}', '\u{0}', '\u{0}']), ('\u{4e8}', ['\u{4e9}', '\u{0}', '\u{0}']),
+        ('\u{4ea}', ['\u{4eb}', '\u{0}', '\u{0}']), ('\u{4ec}', ['\u{4ed}', '\u{0}', '\u{0}']),
+        ('\u{4ee}', ['\u{4ef}', '\u{0}', '\u{0}']), ('\u{4f0}', ['\u{4f1}', '\u{0}', '\u{0}']),
+        ('\u{4f2}', ['\u{4f3}', '\u{0}', '\u{0}']), ('\u{4f4}', ['\u{4f5}', '\u{0}', '\u{0}']),
+        ('\u{4f6}', ['\u{4f7}', '\u{0}', '\u{0}']), ('\u{4f8}', ['\u{4f9}', '\u{0}', '\u{0}']),
+        ('\u{4fa}', ['\u{4fb}', '\u{0}', '\u{0}']), ('\u{4fc}', ['\u{4fd}', '\u{0}', '\u{0}']),
+        ('\u{4fe}', ['\u{4ff}', '\u{0}', '\u{0}']), ('\u{500}', ['\u{501}', '\u{0}', '\u{0}']),
+        ('\u{502}', ['\u{503}', '\u{0}', '\u{0}']), ('\u{504}', ['\u{505}', '\u{0}', '\u{0}']),
+        ('\u{506}', ['\u{507}', '\u{0}', '\u{0}']), ('\u{508}', ['\u{509}', '\u{0}', '\u{0}']),
+        ('\u{50a}', ['\u{50b}', '\u{0}', '\u{0}']), ('\u{50c}', ['\u{50d}', '\u{0}', '\u{0}']),
+        ('\u{50e}', ['\u{50f}', '\u{0}', '\u{0}']), ('\u{510}', ['\u{511}', '\u{0}', '\u{0}']),
+        ('\u{512}', ['\u{513}', '\u{0}', '\u{0}']), ('\u{514}', ['\u{515}', '\u{0}', '\u{0}']),
+        ('\u{516}', ['\u{517}', '\u{0}', '\u{0}']), ('\u{518}', ['\u{519}', '\u{0}', '\u{0}']),
+        ('\u{51a}', ['\u{51b}', '\u{0}', '\u{0}']), ('\u{51c}', ['\u{51d}', '\u{0}', '\u{0}']),
+        ('\u{51e}', ['\u{51f}', '\u{0}', '\u{0}']), ('\u{520}', ['\u{521}', '\u{0}', '\u{0}']),
+        ('\u{522}', ['\u{523}', '\u{0}', '\u{0}']), ('\u{524}', ['\u{525}', '\u{0}', '\u{0}']),
+        ('\u{526}', ['\u{527}', '\u{0}', '\u{0}']), ('\u{528}', ['\u{529}', '\u{0}', '\u{0}']),
+        ('\u{52a}', ['\u{52b}', '\u{0}', '\u{0}']), ('\u{52c}', ['\u{52d}', '\u{0}', '\u{0}']),
+        ('\u{52e}', ['\u{52f}', '\u{0}', '\u{0}']), ('\u{531}', ['\u{561}', '\u{0}', '\u{0}']),
+        ('\u{532}', ['\u{562}', '\u{0}', '\u{0}']), ('\u{533}', ['\u{563}', '\u{0}', '\u{0}']),
+        ('\u{534}', ['\u{564}', '\u{0}', '\u{0}']), ('\u{535}', ['\u{565}', '\u{0}', '\u{0}']),
+        ('\u{536}', ['\u{566}', '\u{0}', '\u{0}']), ('\u{537}', ['\u{567}', '\u{0}', '\u{0}']),
+        ('\u{538}', ['\u{568}', '\u{0}', '\u{0}']), ('\u{539}', ['\u{569}', '\u{0}', '\u{0}']),
+        ('\u{53a}', ['\u{56a}', '\u{0}', '\u{0}']), ('\u{53b}', ['\u{56b}', '\u{0}', '\u{0}']),
+        ('\u{53c}', ['\u{56c}', '\u{0}', '\u{0}']), ('\u{53d}', ['\u{56d}', '\u{0}', '\u{0}']),
+        ('\u{53e}', ['\u{56e}', '\u{0}', '\u{0}']), ('\u{53f}', ['\u{56f}', '\u{0}', '\u{0}']),
+        ('\u{540}', ['\u{570}', '\u{0}', '\u{0}']), ('\u{541}', ['\u{571}', '\u{0}', '\u{0}']),
+        ('\u{542}', ['\u{572}', '\u{0}', '\u{0}']), ('\u{543}', ['\u{573}', '\u{0}', '\u{0}']),
+        ('\u{544}', ['\u{574}', '\u{0}', '\u{0}']), ('\u{545}', ['\u{575}', '\u{0}', '\u{0}']),
+        ('\u{546}', ['\u{576}', '\u{0}', '\u{0}']), ('\u{547}', ['\u{577}', '\u{0}', '\u{0}']),
+        ('\u{548}', ['\u{578}', '\u{0}', '\u{0}']), ('\u{549}', ['\u{579}', '\u{0}', '\u{0}']),
+        ('\u{54a}', ['\u{57a}', '\u{0}', '\u{0}']), ('\u{54b}', ['\u{57b}', '\u{0}', '\u{0}']),
+        ('\u{54c}', ['\u{57c}', '\u{0}', '\u{0}']), ('\u{54d}', ['\u{57d}', '\u{0}', '\u{0}']),
+        ('\u{54e}', ['\u{57e}', '\u{0}', '\u{0}']), ('\u{54f}', ['\u{57f}', '\u{0}', '\u{0}']),
+        ('\u{550}', ['\u{580}', '\u{0}', '\u{0}']), ('\u{551}', ['\u{581}', '\u{0}', '\u{0}']),
+        ('\u{552}', ['\u{582}', '\u{0}', '\u{0}']), ('\u{553}', ['\u{583}', '\u{0}', '\u{0}']),
+        ('\u{554}', ['\u{584}', '\u{0}', '\u{0}']), ('\u{555}', ['\u{585}', '\u{0}', '\u{0}']),
+        ('\u{556}', ['\u{586}', '\u{0}', '\u{0}']), ('\u{10a0}', ['\u{2d00}', '\u{0}', '\u{0}']),
+        ('\u{10a1}', ['\u{2d01}', '\u{0}', '\u{0}']), ('\u{10a2}', ['\u{2d02}', '\u{0}', '\u{0}']),
+        ('\u{10a3}', ['\u{2d03}', '\u{0}', '\u{0}']), ('\u{10a4}', ['\u{2d04}', '\u{0}', '\u{0}']),
+        ('\u{10a5}', ['\u{2d05}', '\u{0}', '\u{0}']), ('\u{10a6}', ['\u{2d06}', '\u{0}', '\u{0}']),
+        ('\u{10a7}', ['\u{2d07}', '\u{0}', '\u{0}']), ('\u{10a8}', ['\u{2d08}', '\u{0}', '\u{0}']),
+        ('\u{10a9}', ['\u{2d09}', '\u{0}', '\u{0}']), ('\u{10aa}', ['\u{2d0a}', '\u{0}', '\u{0}']),
+        ('\u{10ab}', ['\u{2d0b}', '\u{0}', '\u{0}']), ('\u{10ac}', ['\u{2d0c}', '\u{0}', '\u{0}']),
+        ('\u{10ad}', ['\u{2d0d}', '\u{0}', '\u{0}']), ('\u{10ae}', ['\u{2d0e}', '\u{0}', '\u{0}']),
+        ('\u{10af}', ['\u{2d0f}', '\u{0}', '\u{0}']), ('\u{10b0}', ['\u{2d10}', '\u{0}', '\u{0}']),
+        ('\u{10b1}', ['\u{2d11}', '\u{0}', '\u{0}']), ('\u{10b2}', ['\u{2d12}', '\u{0}', '\u{0}']),
+        ('\u{10b3}', ['\u{2d13}', '\u{0}', '\u{0}']), ('\u{10b4}', ['\u{2d14}', '\u{0}', '\u{0}']),
+        ('\u{10b5}', ['\u{2d15}', '\u{0}', '\u{0}']), ('\u{10b6}', ['\u{2d16}', '\u{0}', '\u{0}']),
+        ('\u{10b7}', ['\u{2d17}', '\u{0}', '\u{0}']), ('\u{10b8}', ['\u{2d18}', '\u{0}', '\u{0}']),
+        ('\u{10b9}', ['\u{2d19}', '\u{0}', '\u{0}']), ('\u{10ba}', ['\u{2d1a}', '\u{0}', '\u{0}']),
+        ('\u{10bb}', ['\u{2d1b}', '\u{0}', '\u{0}']), ('\u{10bc}', ['\u{2d1c}', '\u{0}', '\u{0}']),
+        ('\u{10bd}', ['\u{2d1d}', '\u{0}', '\u{0}']), ('\u{10be}', ['\u{2d1e}', '\u{0}', '\u{0}']),
+        ('\u{10bf}', ['\u{2d1f}', '\u{0}', '\u{0}']), ('\u{10c0}', ['\u{2d20}', '\u{0}', '\u{0}']),
+        ('\u{10c1}', ['\u{2d21}', '\u{0}', '\u{0}']), ('\u{10c2}', ['\u{2d22}', '\u{0}', '\u{0}']),
+        ('\u{10c3}', ['\u{2d23}', '\u{0}', '\u{0}']), ('\u{10c4}', ['\u{2d24}', '\u{0}', '\u{0}']),
+        ('\u{10c5}', ['\u{2d25}', '\u{0}', '\u{0}']), ('\u{10c7}', ['\u{2d27}', '\u{0}', '\u{0}']),
+        ('\u{10cd}', ['\u{2d2d}', '\u{0}', '\u{0}']), ('\u{13a0}', ['\u{ab70}', '\u{0}', '\u{0}']),
+        ('\u{13a1}', ['\u{ab71}', '\u{0}', '\u{0}']), ('\u{13a2}', ['\u{ab72}', '\u{0}', '\u{0}']),
+        ('\u{13a3}', ['\u{ab73}', '\u{0}', '\u{0}']), ('\u{13a4}', ['\u{ab74}', '\u{0}', '\u{0}']),
+        ('\u{13a5}', ['\u{ab75}', '\u{0}', '\u{0}']), ('\u{13a6}', ['\u{ab76}', '\u{0}', '\u{0}']),
+        ('\u{13a7}', ['\u{ab77}', '\u{0}', '\u{0}']), ('\u{13a8}', ['\u{ab78}', '\u{0}', '\u{0}']),
+        ('\u{13a9}', ['\u{ab79}', '\u{0}', '\u{0}']), ('\u{13aa}', ['\u{ab7a}', '\u{0}', '\u{0}']),
+        ('\u{13ab}', ['\u{ab7b}', '\u{0}', '\u{0}']), ('\u{13ac}', ['\u{ab7c}', '\u{0}', '\u{0}']),
+        ('\u{13ad}', ['\u{ab7d}', '\u{0}', '\u{0}']), ('\u{13ae}', ['\u{ab7e}', '\u{0}', '\u{0}']),
+        ('\u{13af}', ['\u{ab7f}', '\u{0}', '\u{0}']), ('\u{13b0}', ['\u{ab80}', '\u{0}', '\u{0}']),
+        ('\u{13b1}', ['\u{ab81}', '\u{0}', '\u{0}']), ('\u{13b2}', ['\u{ab82}', '\u{0}', '\u{0}']),
+        ('\u{13b3}', ['\u{ab83}', '\u{0}', '\u{0}']), ('\u{13b4}', ['\u{ab84}', '\u{0}', '\u{0}']),
+        ('\u{13b5}', ['\u{ab85}', '\u{0}', '\u{0}']), ('\u{13b6}', ['\u{ab86}', '\u{0}', '\u{0}']),
+        ('\u{13b7}', ['\u{ab87}', '\u{0}', '\u{0}']), ('\u{13b8}', ['\u{ab88}', '\u{0}', '\u{0}']),
+        ('\u{13b9}', ['\u{ab89}', '\u{0}', '\u{0}']), ('\u{13ba}', ['\u{ab8a}', '\u{0}', '\u{0}']),
+        ('\u{13bb}', ['\u{ab8b}', '\u{0}', '\u{0}']), ('\u{13bc}', ['\u{ab8c}', '\u{0}', '\u{0}']),
+        ('\u{13bd}', ['\u{ab8d}', '\u{0}', '\u{0}']), ('\u{13be}', ['\u{ab8e}', '\u{0}', '\u{0}']),
+        ('\u{13bf}', ['\u{ab8f}', '\u{0}', '\u{0}']), ('\u{13c0}', ['\u{ab90}', '\u{0}', '\u{0}']),
+        ('\u{13c1}', ['\u{ab91}', '\u{0}', '\u{0}']), ('\u{13c2}', ['\u{ab92}', '\u{0}', '\u{0}']),
+        ('\u{13c3}', ['\u{ab93}', '\u{0}', '\u{0}']), ('\u{13c4}', ['\u{ab94}', '\u{0}', '\u{0}']),
+        ('\u{13c5}', ['\u{ab95}', '\u{0}', '\u{0}']), ('\u{13c6}', ['\u{ab96}', '\u{0}', '\u{0}']),
+        ('\u{13c7}', ['\u{ab97}', '\u{0}', '\u{0}']), ('\u{13c8}', ['\u{ab98}', '\u{0}', '\u{0}']),
+        ('\u{13c9}', ['\u{ab99}', '\u{0}', '\u{0}']), ('\u{13ca}', ['\u{ab9a}', '\u{0}', '\u{0}']),
+        ('\u{13cb}', ['\u{ab9b}', '\u{0}', '\u{0}']), ('\u{13cc}', ['\u{ab9c}', '\u{0}', '\u{0}']),
+        ('\u{13cd}', ['\u{ab9d}', '\u{0}', '\u{0}']), ('\u{13ce}', ['\u{ab9e}', '\u{0}', '\u{0}']),
+        ('\u{13cf}', ['\u{ab9f}', '\u{0}', '\u{0}']), ('\u{13d0}', ['\u{aba0}', '\u{0}', '\u{0}']),
+        ('\u{13d1}', ['\u{aba1}', '\u{0}', '\u{0}']), ('\u{13d2}', ['\u{aba2}', '\u{0}', '\u{0}']),
+        ('\u{13d3}', ['\u{aba3}', '\u{0}', '\u{0}']), ('\u{13d4}', ['\u{aba4}', '\u{0}', '\u{0}']),
+        ('\u{13d5}', ['\u{aba5}', '\u{0}', '\u{0}']), ('\u{13d6}', ['\u{aba6}', '\u{0}', '\u{0}']),
+        ('\u{13d7}', ['\u{aba7}', '\u{0}', '\u{0}']), ('\u{13d8}', ['\u{aba8}', '\u{0}', '\u{0}']),
+        ('\u{13d9}', ['\u{aba9}', '\u{0}', '\u{0}']), ('\u{13da}', ['\u{abaa}', '\u{0}', '\u{0}']),
+        ('\u{13db}', ['\u{abab}', '\u{0}', '\u{0}']), ('\u{13dc}', ['\u{abac}', '\u{0}', '\u{0}']),
+        ('\u{13dd}', ['\u{abad}', '\u{0}', '\u{0}']), ('\u{13de}', ['\u{abae}', '\u{0}', '\u{0}']),
+        ('\u{13df}', ['\u{abaf}', '\u{0}', '\u{0}']), ('\u{13e0}', ['\u{abb0}', '\u{0}', '\u{0}']),
+        ('\u{13e1}', ['\u{abb1}', '\u{0}', '\u{0}']), ('\u{13e2}', ['\u{abb2}', '\u{0}', '\u{0}']),
+        ('\u{13e3}', ['\u{abb3}', '\u{0}', '\u{0}']), ('\u{13e4}', ['\u{abb4}', '\u{0}', '\u{0}']),
+        ('\u{13e5}', ['\u{abb5}', '\u{0}', '\u{0}']), ('\u{13e6}', ['\u{abb6}', '\u{0}', '\u{0}']),
+        ('\u{13e7}', ['\u{abb7}', '\u{0}', '\u{0}']), ('\u{13e8}', ['\u{abb8}', '\u{0}', '\u{0}']),
+        ('\u{13e9}', ['\u{abb9}', '\u{0}', '\u{0}']), ('\u{13ea}', ['\u{abba}', '\u{0}', '\u{0}']),
+        ('\u{13eb}', ['\u{abbb}', '\u{0}', '\u{0}']), ('\u{13ec}', ['\u{abbc}', '\u{0}', '\u{0}']),
+        ('\u{13ed}', ['\u{abbd}', '\u{0}', '\u{0}']), ('\u{13ee}', ['\u{abbe}', '\u{0}', '\u{0}']),
+        ('\u{13ef}', ['\u{abbf}', '\u{0}', '\u{0}']), ('\u{13f0}', ['\u{13f8}', '\u{0}', '\u{0}']),
+        ('\u{13f1}', ['\u{13f9}', '\u{0}', '\u{0}']), ('\u{13f2}', ['\u{13fa}', '\u{0}', '\u{0}']),
+        ('\u{13f3}', ['\u{13fb}', '\u{0}', '\u{0}']), ('\u{13f4}', ['\u{13fc}', '\u{0}', '\u{0}']),
+        ('\u{13f5}', ['\u{13fd}', '\u{0}', '\u{0}']), ('\u{1c90}', ['\u{10d0}', '\u{0}', '\u{0}']),
+        ('\u{1c91}', ['\u{10d1}', '\u{0}', '\u{0}']), ('\u{1c92}', ['\u{10d2}', '\u{0}', '\u{0}']),
+        ('\u{1c93}', ['\u{10d3}', '\u{0}', '\u{0}']), ('\u{1c94}', ['\u{10d4}', '\u{0}', '\u{0}']),
+        ('\u{1c95}', ['\u{10d5}', '\u{0}', '\u{0}']), ('\u{1c96}', ['\u{10d6}', '\u{0}', '\u{0}']),
+        ('\u{1c97}', ['\u{10d7}', '\u{0}', '\u{0}']), ('\u{1c98}', ['\u{10d8}', '\u{0}', '\u{0}']),
+        ('\u{1c99}', ['\u{10d9}', '\u{0}', '\u{0}']), ('\u{1c9a}', ['\u{10da}', '\u{0}', '\u{0}']),
+        ('\u{1c9b}', ['\u{10db}', '\u{0}', '\u{0}']), ('\u{1c9c}', ['\u{10dc}', '\u{0}', '\u{0}']),
+        ('\u{1c9d}', ['\u{10dd}', '\u{0}', '\u{0}']), ('\u{1c9e}', ['\u{10de}', '\u{0}', '\u{0}']),
+        ('\u{1c9f}', ['\u{10df}', '\u{0}', '\u{0}']), ('\u{1ca0}', ['\u{10e0}', '\u{0}', '\u{0}']),
+        ('\u{1ca1}', ['\u{10e1}', '\u{0}', '\u{0}']), ('\u{1ca2}', ['\u{10e2}', '\u{0}', '\u{0}']),
+        ('\u{1ca3}', ['\u{10e3}', '\u{0}', '\u{0}']), ('\u{1ca4}', ['\u{10e4}', '\u{0}', '\u{0}']),
+        ('\u{1ca5}', ['\u{10e5}', '\u{0}', '\u{0}']), ('\u{1ca6}', ['\u{10e6}', '\u{0}', '\u{0}']),
+        ('\u{1ca7}', ['\u{10e7}', '\u{0}', '\u{0}']), ('\u{1ca8}', ['\u{10e8}', '\u{0}', '\u{0}']),
+        ('\u{1ca9}', ['\u{10e9}', '\u{0}', '\u{0}']), ('\u{1caa}', ['\u{10ea}', '\u{0}', '\u{0}']),
+        ('\u{1cab}', ['\u{10eb}', '\u{0}', '\u{0}']), ('\u{1cac}', ['\u{10ec}', '\u{0}', '\u{0}']),
+        ('\u{1cad}', ['\u{10ed}', '\u{0}', '\u{0}']), ('\u{1cae}', ['\u{10ee}', '\u{0}', '\u{0}']),
+        ('\u{1caf}', ['\u{10ef}', '\u{0}', '\u{0}']), ('\u{1cb0}', ['\u{10f0}', '\u{0}', '\u{0}']),
+        ('\u{1cb1}', ['\u{10f1}', '\u{0}', '\u{0}']), ('\u{1cb2}', ['\u{10f2}', '\u{0}', '\u{0}']),
+        ('\u{1cb3}', ['\u{10f3}', '\u{0}', '\u{0}']), ('\u{1cb4}', ['\u{10f4}', '\u{0}', '\u{0}']),
+        ('\u{1cb5}', ['\u{10f5}', '\u{0}', '\u{0}']), ('\u{1cb6}', ['\u{10f6}', '\u{0}', '\u{0}']),
+        ('\u{1cb7}', ['\u{10f7}', '\u{0}', '\u{0}']), ('\u{1cb8}', ['\u{10f8}', '\u{0}', '\u{0}']),
+        ('\u{1cb9}', ['\u{10f9}', '\u{0}', '\u{0}']), ('\u{1cba}', ['\u{10fa}', '\u{0}', '\u{0}']),
+        ('\u{1cbd}', ['\u{10fd}', '\u{0}', '\u{0}']), ('\u{1cbe}', ['\u{10fe}', '\u{0}', '\u{0}']),
+        ('\u{1cbf}', ['\u{10ff}', '\u{0}', '\u{0}']), ('\u{1e00}', ['\u{1e01}', '\u{0}', '\u{0}']),
+        ('\u{1e02}', ['\u{1e03}', '\u{0}', '\u{0}']), ('\u{1e04}', ['\u{1e05}', '\u{0}', '\u{0}']),
+        ('\u{1e06}', ['\u{1e07}', '\u{0}', '\u{0}']), ('\u{1e08}', ['\u{1e09}', '\u{0}', '\u{0}']),
+        ('\u{1e0a}', ['\u{1e0b}', '\u{0}', '\u{0}']), ('\u{1e0c}', ['\u{1e0d}', '\u{0}', '\u{0}']),
+        ('\u{1e0e}', ['\u{1e0f}', '\u{0}', '\u{0}']), ('\u{1e10}', ['\u{1e11}', '\u{0}', '\u{0}']),
+        ('\u{1e12}', ['\u{1e13}', '\u{0}', '\u{0}']), ('\u{1e14}', ['\u{1e15}', '\u{0}', '\u{0}']),
+        ('\u{1e16}', ['\u{1e17}', '\u{0}', '\u{0}']), ('\u{1e18}', ['\u{1e19}', '\u{0}', '\u{0}']),
+        ('\u{1e1a}', ['\u{1e1b}', '\u{0}', '\u{0}']), ('\u{1e1c}', ['\u{1e1d}', '\u{0}', '\u{0}']),
+        ('\u{1e1e}', ['\u{1e1f}', '\u{0}', '\u{0}']), ('\u{1e20}', ['\u{1e21}', '\u{0}', '\u{0}']),
+        ('\u{1e22}', ['\u{1e23}', '\u{0}', '\u{0}']), ('\u{1e24}', ['\u{1e25}', '\u{0}', '\u{0}']),
+        ('\u{1e26}', ['\u{1e27}', '\u{0}', '\u{0}']), ('\u{1e28}', ['\u{1e29}', '\u{0}', '\u{0}']),
+        ('\u{1e2a}', ['\u{1e2b}', '\u{0}', '\u{0}']), ('\u{1e2c}', ['\u{1e2d}', '\u{0}', '\u{0}']),
+        ('\u{1e2e}', ['\u{1e2f}', '\u{0}', '\u{0}']), ('\u{1e30}', ['\u{1e31}', '\u{0}', '\u{0}']),
+        ('\u{1e32}', ['\u{1e33}', '\u{0}', '\u{0}']), ('\u{1e34}', ['\u{1e35}', '\u{0}', '\u{0}']),
+        ('\u{1e36}', ['\u{1e37}', '\u{0}', '\u{0}']), ('\u{1e38}', ['\u{1e39}', '\u{0}', '\u{0}']),
+        ('\u{1e3a}', ['\u{1e3b}', '\u{0}', '\u{0}']), ('\u{1e3c}', ['\u{1e3d}', '\u{0}', '\u{0}']),
+        ('\u{1e3e}', ['\u{1e3f}', '\u{0}', '\u{0}']), ('\u{1e40}', ['\u{1e41}', '\u{0}', '\u{0}']),
+        ('\u{1e42}', ['\u{1e43}', '\u{0}', '\u{0}']), ('\u{1e44}', ['\u{1e45}', '\u{0}', '\u{0}']),
+        ('\u{1e46}', ['\u{1e47}', '\u{0}', '\u{0}']), ('\u{1e48}', ['\u{1e49}', '\u{0}', '\u{0}']),
+        ('\u{1e4a}', ['\u{1e4b}', '\u{0}', '\u{0}']), ('\u{1e4c}', ['\u{1e4d}', '\u{0}', '\u{0}']),
+        ('\u{1e4e}', ['\u{1e4f}', '\u{0}', '\u{0}']), ('\u{1e50}', ['\u{1e51}', '\u{0}', '\u{0}']),
+        ('\u{1e52}', ['\u{1e53}', '\u{0}', '\u{0}']), ('\u{1e54}', ['\u{1e55}', '\u{0}', '\u{0}']),
+        ('\u{1e56}', ['\u{1e57}', '\u{0}', '\u{0}']), ('\u{1e58}', ['\u{1e59}', '\u{0}', '\u{0}']),
+        ('\u{1e5a}', ['\u{1e5b}', '\u{0}', '\u{0}']), ('\u{1e5c}', ['\u{1e5d}', '\u{0}', '\u{0}']),
+        ('\u{1e5e}', ['\u{1e5f}', '\u{0}', '\u{0}']), ('\u{1e60}', ['\u{1e61}', '\u{0}', '\u{0}']),
+        ('\u{1e62}', ['\u{1e63}', '\u{0}', '\u{0}']), ('\u{1e64}', ['\u{1e65}', '\u{0}', '\u{0}']),
+        ('\u{1e66}', ['\u{1e67}', '\u{0}', '\u{0}']), ('\u{1e68}', ['\u{1e69}', '\u{0}', '\u{0}']),
+        ('\u{1e6a}', ['\u{1e6b}', '\u{0}', '\u{0}']), ('\u{1e6c}', ['\u{1e6d}', '\u{0}', '\u{0}']),
+        ('\u{1e6e}', ['\u{1e6f}', '\u{0}', '\u{0}']), ('\u{1e70}', ['\u{1e71}', '\u{0}', '\u{0}']),
+        ('\u{1e72}', ['\u{1e73}', '\u{0}', '\u{0}']), ('\u{1e74}', ['\u{1e75}', '\u{0}', '\u{0}']),
+        ('\u{1e76}', ['\u{1e77}', '\u{0}', '\u{0}']), ('\u{1e78}', ['\u{1e79}', '\u{0}', '\u{0}']),
+        ('\u{1e7a}', ['\u{1e7b}', '\u{0}', '\u{0}']), ('\u{1e7c}', ['\u{1e7d}', '\u{0}', '\u{0}']),
+        ('\u{1e7e}', ['\u{1e7f}', '\u{0}', '\u{0}']), ('\u{1e80}', ['\u{1e81}', '\u{0}', '\u{0}']),
+        ('\u{1e82}', ['\u{1e83}', '\u{0}', '\u{0}']), ('\u{1e84}', ['\u{1e85}', '\u{0}', '\u{0}']),
+        ('\u{1e86}', ['\u{1e87}', '\u{0}', '\u{0}']), ('\u{1e88}', ['\u{1e89}', '\u{0}', '\u{0}']),
+        ('\u{1e8a}', ['\u{1e8b}', '\u{0}', '\u{0}']), ('\u{1e8c}', ['\u{1e8d}', '\u{0}', '\u{0}']),
+        ('\u{1e8e}', ['\u{1e8f}', '\u{0}', '\u{0}']), ('\u{1e90}', ['\u{1e91}', '\u{0}', '\u{0}']),
+        ('\u{1e92}', ['\u{1e93}', '\u{0}', '\u{0}']), ('\u{1e94}', ['\u{1e95}', '\u{0}', '\u{0}']),
+        ('\u{1e9e}', ['\u{df}', '\u{0}', '\u{0}']), ('\u{1ea0}', ['\u{1ea1}', '\u{0}', '\u{0}']),
+        ('\u{1ea2}', ['\u{1ea3}', '\u{0}', '\u{0}']), ('\u{1ea4}', ['\u{1ea5}', '\u{0}', '\u{0}']),
+        ('\u{1ea6}', ['\u{1ea7}', '\u{0}', '\u{0}']), ('\u{1ea8}', ['\u{1ea9}', '\u{0}', '\u{0}']),
+        ('\u{1eaa}', ['\u{1eab}', '\u{0}', '\u{0}']), ('\u{1eac}', ['\u{1ead}', '\u{0}', '\u{0}']),
+        ('\u{1eae}', ['\u{1eaf}', '\u{0}', '\u{0}']), ('\u{1eb0}', ['\u{1eb1}', '\u{0}', '\u{0}']),
+        ('\u{1eb2}', ['\u{1eb3}', '\u{0}', '\u{0}']), ('\u{1eb4}', ['\u{1eb5}', '\u{0}', '\u{0}']),
+        ('\u{1eb6}', ['\u{1eb7}', '\u{0}', '\u{0}']), ('\u{1eb8}', ['\u{1eb9}', '\u{0}', '\u{0}']),
+        ('\u{1eba}', ['\u{1ebb}', '\u{0}', '\u{0}']), ('\u{1ebc}', ['\u{1ebd}', '\u{0}', '\u{0}']),
+        ('\u{1ebe}', ['\u{1ebf}', '\u{0}', '\u{0}']), ('\u{1ec0}', ['\u{1ec1}', '\u{0}', '\u{0}']),
+        ('\u{1ec2}', ['\u{1ec3}', '\u{0}', '\u{0}']), ('\u{1ec4}', ['\u{1ec5}', '\u{0}', '\u{0}']),
+        ('\u{1ec6}', ['\u{1ec7}', '\u{0}', '\u{0}']), ('\u{1ec8}', ['\u{1ec9}', '\u{0}', '\u{0}']),
+        ('\u{1eca}', ['\u{1ecb}', '\u{0}', '\u{0}']), ('\u{1ecc}', ['\u{1ecd}', '\u{0}', '\u{0}']),
+        ('\u{1ece}', ['\u{1ecf}', '\u{0}', '\u{0}']), ('\u{1ed0}', ['\u{1ed1}', '\u{0}', '\u{0}']),
+        ('\u{1ed2}', ['\u{1ed3}', '\u{0}', '\u{0}']), ('\u{1ed4}', ['\u{1ed5}', '\u{0}', '\u{0}']),
+        ('\u{1ed6}', ['\u{1ed7}', '\u{0}', '\u{0}']), ('\u{1ed8}', ['\u{1ed9}', '\u{0}', '\u{0}']),
+        ('\u{1eda}', ['\u{1edb}', '\u{0}', '\u{0}']), ('\u{1edc}', ['\u{1edd}', '\u{0}', '\u{0}']),
+        ('\u{1ede}', ['\u{1edf}', '\u{0}', '\u{0}']), ('\u{1ee0}', ['\u{1ee1}', '\u{0}', '\u{0}']),
+        ('\u{1ee2}', ['\u{1ee3}', '\u{0}', '\u{0}']), ('\u{1ee4}', ['\u{1ee5}', '\u{0}', '\u{0}']),
+        ('\u{1ee6}', ['\u{1ee7}', '\u{0}', '\u{0}']), ('\u{1ee8}', ['\u{1ee9}', '\u{0}', '\u{0}']),
+        ('\u{1eea}', ['\u{1eeb}', '\u{0}', '\u{0}']), ('\u{1eec}', ['\u{1eed}', '\u{0}', '\u{0}']),
+        ('\u{1eee}', ['\u{1eef}', '\u{0}', '\u{0}']), ('\u{1ef0}', ['\u{1ef1}', '\u{0}', '\u{0}']),
+        ('\u{1ef2}', ['\u{1ef3}', '\u{0}', '\u{0}']), ('\u{1ef4}', ['\u{1ef5}', '\u{0}', '\u{0}']),
+        ('\u{1ef6}', ['\u{1ef7}', '\u{0}', '\u{0}']), ('\u{1ef8}', ['\u{1ef9}', '\u{0}', '\u{0}']),
+        ('\u{1efa}', ['\u{1efb}', '\u{0}', '\u{0}']), ('\u{1efc}', ['\u{1efd}', '\u{0}', '\u{0}']),
+        ('\u{1efe}', ['\u{1eff}', '\u{0}', '\u{0}']), ('\u{1f08}', ['\u{1f00}', '\u{0}', '\u{0}']),
+        ('\u{1f09}', ['\u{1f01}', '\u{0}', '\u{0}']), ('\u{1f0a}', ['\u{1f02}', '\u{0}', '\u{0}']),
+        ('\u{1f0b}', ['\u{1f03}', '\u{0}', '\u{0}']), ('\u{1f0c}', ['\u{1f04}', '\u{0}', '\u{0}']),
+        ('\u{1f0d}', ['\u{1f05}', '\u{0}', '\u{0}']), ('\u{1f0e}', ['\u{1f06}', '\u{0}', '\u{0}']),
+        ('\u{1f0f}', ['\u{1f07}', '\u{0}', '\u{0}']), ('\u{1f18}', ['\u{1f10}', '\u{0}', '\u{0}']),
+        ('\u{1f19}', ['\u{1f11}', '\u{0}', '\u{0}']), ('\u{1f1a}', ['\u{1f12}', '\u{0}', '\u{0}']),
+        ('\u{1f1b}', ['\u{1f13}', '\u{0}', '\u{0}']), ('\u{1f1c}', ['\u{1f14}', '\u{0}', '\u{0}']),
+        ('\u{1f1d}', ['\u{1f15}', '\u{0}', '\u{0}']), ('\u{1f28}', ['\u{1f20}', '\u{0}', '\u{0}']),
+        ('\u{1f29}', ['\u{1f21}', '\u{0}', '\u{0}']), ('\u{1f2a}', ['\u{1f22}', '\u{0}', '\u{0}']),
+        ('\u{1f2b}', ['\u{1f23}', '\u{0}', '\u{0}']), ('\u{1f2c}', ['\u{1f24}', '\u{0}', '\u{0}']),
+        ('\u{1f2d}', ['\u{1f25}', '\u{0}', '\u{0}']), ('\u{1f2e}', ['\u{1f26}', '\u{0}', '\u{0}']),
+        ('\u{1f2f}', ['\u{1f27}', '\u{0}', '\u{0}']), ('\u{1f38}', ['\u{1f30}', '\u{0}', '\u{0}']),
+        ('\u{1f39}', ['\u{1f31}', '\u{0}', '\u{0}']), ('\u{1f3a}', ['\u{1f32}', '\u{0}', '\u{0}']),
+        ('\u{1f3b}', ['\u{1f33}', '\u{0}', '\u{0}']), ('\u{1f3c}', ['\u{1f34}', '\u{0}', '\u{0}']),
+        ('\u{1f3d}', ['\u{1f35}', '\u{0}', '\u{0}']), ('\u{1f3e}', ['\u{1f36}', '\u{0}', '\u{0}']),
+        ('\u{1f3f}', ['\u{1f37}', '\u{0}', '\u{0}']), ('\u{1f48}', ['\u{1f40}', '\u{0}', '\u{0}']),
+        ('\u{1f49}', ['\u{1f41}', '\u{0}', '\u{0}']), ('\u{1f4a}', ['\u{1f42}', '\u{0}', '\u{0}']),
+        ('\u{1f4b}', ['\u{1f43}', '\u{0}', '\u{0}']), ('\u{1f4c}', ['\u{1f44}', '\u{0}', '\u{0}']),
+        ('\u{1f4d}', ['\u{1f45}', '\u{0}', '\u{0}']), ('\u{1f59}', ['\u{1f51}', '\u{0}', '\u{0}']),
+        ('\u{1f5b}', ['\u{1f53}', '\u{0}', '\u{0}']), ('\u{1f5d}', ['\u{1f55}', '\u{0}', '\u{0}']),
+        ('\u{1f5f}', ['\u{1f57}', '\u{0}', '\u{0}']), ('\u{1f68}', ['\u{1f60}', '\u{0}', '\u{0}']),
+        ('\u{1f69}', ['\u{1f61}', '\u{0}', '\u{0}']), ('\u{1f6a}', ['\u{1f62}', '\u{0}', '\u{0}']),
+        ('\u{1f6b}', ['\u{1f63}', '\u{0}', '\u{0}']), ('\u{1f6c}', ['\u{1f64}', '\u{0}', '\u{0}']),
+        ('\u{1f6d}', ['\u{1f65}', '\u{0}', '\u{0}']), ('\u{1f6e}', ['\u{1f66}', '\u{0}', '\u{0}']),
+        ('\u{1f6f}', ['\u{1f67}', '\u{0}', '\u{0}']), ('\u{1f88}', ['\u{1f80}', '\u{0}', '\u{0}']),
+        ('\u{1f89}', ['\u{1f81}', '\u{0}', '\u{0}']), ('\u{1f8a}', ['\u{1f82}', '\u{0}', '\u{0}']),
+        ('\u{1f8b}', ['\u{1f83}', '\u{0}', '\u{0}']), ('\u{1f8c}', ['\u{1f84}', '\u{0}', '\u{0}']),
+        ('\u{1f8d}', ['\u{1f85}', '\u{0}', '\u{0}']), ('\u{1f8e}', ['\u{1f86}', '\u{0}', '\u{0}']),
+        ('\u{1f8f}', ['\u{1f87}', '\u{0}', '\u{0}']), ('\u{1f98}', ['\u{1f90}', '\u{0}', '\u{0}']),
+        ('\u{1f99}', ['\u{1f91}', '\u{0}', '\u{0}']), ('\u{1f9a}', ['\u{1f92}', '\u{0}', '\u{0}']),
+        ('\u{1f9b}', ['\u{1f93}', '\u{0}', '\u{0}']), ('\u{1f9c}', ['\u{1f94}', '\u{0}', '\u{0}']),
+        ('\u{1f9d}', ['\u{1f95}', '\u{0}', '\u{0}']), ('\u{1f9e}', ['\u{1f96}', '\u{0}', '\u{0}']),
+        ('\u{1f9f}', ['\u{1f97}', '\u{0}', '\u{0}']), ('\u{1fa8}', ['\u{1fa0}', '\u{0}', '\u{0}']),
+        ('\u{1fa9}', ['\u{1fa1}', '\u{0}', '\u{0}']), ('\u{1faa}', ['\u{1fa2}', '\u{0}', '\u{0}']),
+        ('\u{1fab}', ['\u{1fa3}', '\u{0}', '\u{0}']), ('\u{1fac}', ['\u{1fa4}', '\u{0}', '\u{0}']),
+        ('\u{1fad}', ['\u{1fa5}', '\u{0}', '\u{0}']), ('\u{1fae}', ['\u{1fa6}', '\u{0}', '\u{0}']),
+        ('\u{1faf}', ['\u{1fa7}', '\u{0}', '\u{0}']), ('\u{1fb8}', ['\u{1fb0}', '\u{0}', '\u{0}']),
+        ('\u{1fb9}', ['\u{1fb1}', '\u{0}', '\u{0}']), ('\u{1fba}', ['\u{1f70}', '\u{0}', '\u{0}']),
+        ('\u{1fbb}', ['\u{1f71}', '\u{0}', '\u{0}']), ('\u{1fbc}', ['\u{1fb3}', '\u{0}', '\u{0}']),
+        ('\u{1fc8}', ['\u{1f72}', '\u{0}', '\u{0}']), ('\u{1fc9}', ['\u{1f73}', '\u{0}', '\u{0}']),
+        ('\u{1fca}', ['\u{1f74}', '\u{0}', '\u{0}']), ('\u{1fcb}', ['\u{1f75}', '\u{0}', '\u{0}']),
+        ('\u{1fcc}', ['\u{1fc3}', '\u{0}', '\u{0}']), ('\u{1fd8}', ['\u{1fd0}', '\u{0}', '\u{0}']),
+        ('\u{1fd9}', ['\u{1fd1}', '\u{0}', '\u{0}']), ('\u{1fda}', ['\u{1f76}', '\u{0}', '\u{0}']),
+        ('\u{1fdb}', ['\u{1f77}', '\u{0}', '\u{0}']), ('\u{1fe8}', ['\u{1fe0}', '\u{0}', '\u{0}']),
+        ('\u{1fe9}', ['\u{1fe1}', '\u{0}', '\u{0}']), ('\u{1fea}', ['\u{1f7a}', '\u{0}', '\u{0}']),
+        ('\u{1feb}', ['\u{1f7b}', '\u{0}', '\u{0}']), ('\u{1fec}', ['\u{1fe5}', '\u{0}', '\u{0}']),
+        ('\u{1ff8}', ['\u{1f78}', '\u{0}', '\u{0}']), ('\u{1ff9}', ['\u{1f79}', '\u{0}', '\u{0}']),
+        ('\u{1ffa}', ['\u{1f7c}', '\u{0}', '\u{0}']), ('\u{1ffb}', ['\u{1f7d}', '\u{0}', '\u{0}']),
+        ('\u{1ffc}', ['\u{1ff3}', '\u{0}', '\u{0}']), ('\u{2126}', ['\u{3c9}', '\u{0}', '\u{0}']),
+        ('\u{212a}', ['k', '\u{0}', '\u{0}']), ('\u{212b}', ['\u{e5}', '\u{0}', '\u{0}']),
+        ('\u{2132}', ['\u{214e}', '\u{0}', '\u{0}']), ('\u{2160}', ['\u{2170}', '\u{0}', '\u{0}']),
+        ('\u{2161}', ['\u{2171}', '\u{0}', '\u{0}']), ('\u{2162}', ['\u{2172}', '\u{0}', '\u{0}']),
+        ('\u{2163}', ['\u{2173}', '\u{0}', '\u{0}']), ('\u{2164}', ['\u{2174}', '\u{0}', '\u{0}']),
+        ('\u{2165}', ['\u{2175}', '\u{0}', '\u{0}']), ('\u{2166}', ['\u{2176}', '\u{0}', '\u{0}']),
+        ('\u{2167}', ['\u{2177}', '\u{0}', '\u{0}']), ('\u{2168}', ['\u{2178}', '\u{0}', '\u{0}']),
+        ('\u{2169}', ['\u{2179}', '\u{0}', '\u{0}']), ('\u{216a}', ['\u{217a}', '\u{0}', '\u{0}']),
+        ('\u{216b}', ['\u{217b}', '\u{0}', '\u{0}']), ('\u{216c}', ['\u{217c}', '\u{0}', '\u{0}']),
+        ('\u{216d}', ['\u{217d}', '\u{0}', '\u{0}']), ('\u{216e}', ['\u{217e}', '\u{0}', '\u{0}']),
+        ('\u{216f}', ['\u{217f}', '\u{0}', '\u{0}']), ('\u{2183}', ['\u{2184}', '\u{0}', '\u{0}']),
+        ('\u{24b6}', ['\u{24d0}', '\u{0}', '\u{0}']), ('\u{24b7}', ['\u{24d1}', '\u{0}', '\u{0}']),
+        ('\u{24b8}', ['\u{24d2}', '\u{0}', '\u{0}']), ('\u{24b9}', ['\u{24d3}', '\u{0}', '\u{0}']),
+        ('\u{24ba}', ['\u{24d4}', '\u{0}', '\u{0}']), ('\u{24bb}', ['\u{24d5}', '\u{0}', '\u{0}']),
+        ('\u{24bc}', ['\u{24d6}', '\u{0}', '\u{0}']), ('\u{24bd}', ['\u{24d7}', '\u{0}', '\u{0}']),
+        ('\u{24be}', ['\u{24d8}', '\u{0}', '\u{0}']), ('\u{24bf}', ['\u{24d9}', '\u{0}', '\u{0}']),
+        ('\u{24c0}', ['\u{24da}', '\u{0}', '\u{0}']), ('\u{24c1}', ['\u{24db}', '\u{0}', '\u{0}']),
+        ('\u{24c2}', ['\u{24dc}', '\u{0}', '\u{0}']), ('\u{24c3}', ['\u{24dd}', '\u{0}', '\u{0}']),
+        ('\u{24c4}', ['\u{24de}', '\u{0}', '\u{0}']), ('\u{24c5}', ['\u{24df}', '\u{0}', '\u{0}']),
+        ('\u{24c6}', ['\u{24e0}', '\u{0}', '\u{0}']), ('\u{24c7}', ['\u{24e1}', '\u{0}', '\u{0}']),
+        ('\u{24c8}', ['\u{24e2}', '\u{0}', '\u{0}']), ('\u{24c9}', ['\u{24e3}', '\u{0}', '\u{0}']),
+        ('\u{24ca}', ['\u{24e4}', '\u{0}', '\u{0}']), ('\u{24cb}', ['\u{24e5}', '\u{0}', '\u{0}']),
+        ('\u{24cc}', ['\u{24e6}', '\u{0}', '\u{0}']), ('\u{24cd}', ['\u{24e7}', '\u{0}', '\u{0}']),
+        ('\u{24ce}', ['\u{24e8}', '\u{0}', '\u{0}']), ('\u{24cf}', ['\u{24e9}', '\u{0}', '\u{0}']),
+        ('\u{2c00}', ['\u{2c30}', '\u{0}', '\u{0}']), ('\u{2c01}', ['\u{2c31}', '\u{0}', '\u{0}']),
+        ('\u{2c02}', ['\u{2c32}', '\u{0}', '\u{0}']), ('\u{2c03}', ['\u{2c33}', '\u{0}', '\u{0}']),
+        ('\u{2c04}', ['\u{2c34}', '\u{0}', '\u{0}']), ('\u{2c05}', ['\u{2c35}', '\u{0}', '\u{0}']),
+        ('\u{2c06}', ['\u{2c36}', '\u{0}', '\u{0}']), ('\u{2c07}', ['\u{2c37}', '\u{0}', '\u{0}']),
+        ('\u{2c08}', ['\u{2c38}', '\u{0}', '\u{0}']), ('\u{2c09}', ['\u{2c39}', '\u{0}', '\u{0}']),
+        ('\u{2c0a}', ['\u{2c3a}', '\u{0}', '\u{0}']), ('\u{2c0b}', ['\u{2c3b}', '\u{0}', '\u{0}']),
+        ('\u{2c0c}', ['\u{2c3c}', '\u{0}', '\u{0}']), ('\u{2c0d}', ['\u{2c3d}', '\u{0}', '\u{0}']),
+        ('\u{2c0e}', ['\u{2c3e}', '\u{0}', '\u{0}']), ('\u{2c0f}', ['\u{2c3f}', '\u{0}', '\u{0}']),
+        ('\u{2c10}', ['\u{2c40}', '\u{0}', '\u{0}']), ('\u{2c11}', ['\u{2c41}', '\u{0}', '\u{0}']),
+        ('\u{2c12}', ['\u{2c42}', '\u{0}', '\u{0}']), ('\u{2c13}', ['\u{2c43}', '\u{0}', '\u{0}']),
+        ('\u{2c14}', ['\u{2c44}', '\u{0}', '\u{0}']), ('\u{2c15}', ['\u{2c45}', '\u{0}', '\u{0}']),
+        ('\u{2c16}', ['\u{2c46}', '\u{0}', '\u{0}']), ('\u{2c17}', ['\u{2c47}', '\u{0}', '\u{0}']),
+        ('\u{2c18}', ['\u{2c48}', '\u{0}', '\u{0}']), ('\u{2c19}', ['\u{2c49}', '\u{0}', '\u{0}']),
+        ('\u{2c1a}', ['\u{2c4a}', '\u{0}', '\u{0}']), ('\u{2c1b}', ['\u{2c4b}', '\u{0}', '\u{0}']),
+        ('\u{2c1c}', ['\u{2c4c}', '\u{0}', '\u{0}']), ('\u{2c1d}', ['\u{2c4d}', '\u{0}', '\u{0}']),
+        ('\u{2c1e}', ['\u{2c4e}', '\u{0}', '\u{0}']), ('\u{2c1f}', ['\u{2c4f}', '\u{0}', '\u{0}']),
+        ('\u{2c20}', ['\u{2c50}', '\u{0}', '\u{0}']), ('\u{2c21}', ['\u{2c51}', '\u{0}', '\u{0}']),
+        ('\u{2c22}', ['\u{2c52}', '\u{0}', '\u{0}']), ('\u{2c23}', ['\u{2c53}', '\u{0}', '\u{0}']),
+        ('\u{2c24}', ['\u{2c54}', '\u{0}', '\u{0}']), ('\u{2c25}', ['\u{2c55}', '\u{0}', '\u{0}']),
+        ('\u{2c26}', ['\u{2c56}', '\u{0}', '\u{0}']), ('\u{2c27}', ['\u{2c57}', '\u{0}', '\u{0}']),
+        ('\u{2c28}', ['\u{2c58}', '\u{0}', '\u{0}']), ('\u{2c29}', ['\u{2c59}', '\u{0}', '\u{0}']),
+        ('\u{2c2a}', ['\u{2c5a}', '\u{0}', '\u{0}']), ('\u{2c2b}', ['\u{2c5b}', '\u{0}', '\u{0}']),
+        ('\u{2c2c}', ['\u{2c5c}', '\u{0}', '\u{0}']), ('\u{2c2d}', ['\u{2c5d}', '\u{0}', '\u{0}']),
+        ('\u{2c2e}', ['\u{2c5e}', '\u{0}', '\u{0}']), ('\u{2c60}', ['\u{2c61}', '\u{0}', '\u{0}']),
+        ('\u{2c62}', ['\u{26b}', '\u{0}', '\u{0}']), ('\u{2c63}', ['\u{1d7d}', '\u{0}', '\u{0}']),
+        ('\u{2c64}', ['\u{27d}', '\u{0}', '\u{0}']), ('\u{2c67}', ['\u{2c68}', '\u{0}', '\u{0}']),
+        ('\u{2c69}', ['\u{2c6a}', '\u{0}', '\u{0}']), ('\u{2c6b}', ['\u{2c6c}', '\u{0}', '\u{0}']),
+        ('\u{2c6d}', ['\u{251}', '\u{0}', '\u{0}']), ('\u{2c6e}', ['\u{271}', '\u{0}', '\u{0}']),
+        ('\u{2c6f}', ['\u{250}', '\u{0}', '\u{0}']), ('\u{2c70}', ['\u{252}', '\u{0}', '\u{0}']),
+        ('\u{2c72}', ['\u{2c73}', '\u{0}', '\u{0}']), ('\u{2c75}', ['\u{2c76}', '\u{0}', '\u{0}']),
+        ('\u{2c7e}', ['\u{23f}', '\u{0}', '\u{0}']), ('\u{2c7f}', ['\u{240}', '\u{0}', '\u{0}']),
+        ('\u{2c80}', ['\u{2c81}', '\u{0}', '\u{0}']), ('\u{2c82}', ['\u{2c83}', '\u{0}', '\u{0}']),
+        ('\u{2c84}', ['\u{2c85}', '\u{0}', '\u{0}']), ('\u{2c86}', ['\u{2c87}', '\u{0}', '\u{0}']),
+        ('\u{2c88}', ['\u{2c89}', '\u{0}', '\u{0}']), ('\u{2c8a}', ['\u{2c8b}', '\u{0}', '\u{0}']),
+        ('\u{2c8c}', ['\u{2c8d}', '\u{0}', '\u{0}']), ('\u{2c8e}', ['\u{2c8f}', '\u{0}', '\u{0}']),
+        ('\u{2c90}', ['\u{2c91}', '\u{0}', '\u{0}']), ('\u{2c92}', ['\u{2c93}', '\u{0}', '\u{0}']),
+        ('\u{2c94}', ['\u{2c95}', '\u{0}', '\u{0}']), ('\u{2c96}', ['\u{2c97}', '\u{0}', '\u{0}']),
+        ('\u{2c98}', ['\u{2c99}', '\u{0}', '\u{0}']), ('\u{2c9a}', ['\u{2c9b}', '\u{0}', '\u{0}']),
+        ('\u{2c9c}', ['\u{2c9d}', '\u{0}', '\u{0}']), ('\u{2c9e}', ['\u{2c9f}', '\u{0}', '\u{0}']),
+        ('\u{2ca0}', ['\u{2ca1}', '\u{0}', '\u{0}']), ('\u{2ca2}', ['\u{2ca3}', '\u{0}', '\u{0}']),
+        ('\u{2ca4}', ['\u{2ca5}', '\u{0}', '\u{0}']), ('\u{2ca6}', ['\u{2ca7}', '\u{0}', '\u{0}']),
+        ('\u{2ca8}', ['\u{2ca9}', '\u{0}', '\u{0}']), ('\u{2caa}', ['\u{2cab}', '\u{0}', '\u{0}']),
+        ('\u{2cac}', ['\u{2cad}', '\u{0}', '\u{0}']), ('\u{2cae}', ['\u{2caf}', '\u{0}', '\u{0}']),
+        ('\u{2cb0}', ['\u{2cb1}', '\u{0}', '\u{0}']), ('\u{2cb2}', ['\u{2cb3}', '\u{0}', '\u{0}']),
+        ('\u{2cb4}', ['\u{2cb5}', '\u{0}', '\u{0}']), ('\u{2cb6}', ['\u{2cb7}', '\u{0}', '\u{0}']),
+        ('\u{2cb8}', ['\u{2cb9}', '\u{0}', '\u{0}']), ('\u{2cba}', ['\u{2cbb}', '\u{0}', '\u{0}']),
+        ('\u{2cbc}', ['\u{2cbd}', '\u{0}', '\u{0}']), ('\u{2cbe}', ['\u{2cbf}', '\u{0}', '\u{0}']),
+        ('\u{2cc0}', ['\u{2cc1}', '\u{0}', '\u{0}']), ('\u{2cc2}', ['\u{2cc3}', '\u{0}', '\u{0}']),
+        ('\u{2cc4}', ['\u{2cc5}', '\u{0}', '\u{0}']), ('\u{2cc6}', ['\u{2cc7}', '\u{0}', '\u{0}']),
+        ('\u{2cc8}', ['\u{2cc9}', '\u{0}', '\u{0}']), ('\u{2cca}', ['\u{2ccb}', '\u{0}', '\u{0}']),
+        ('\u{2ccc}', ['\u{2ccd}', '\u{0}', '\u{0}']), ('\u{2cce}', ['\u{2ccf}', '\u{0}', '\u{0}']),
+        ('\u{2cd0}', ['\u{2cd1}', '\u{0}', '\u{0}']), ('\u{2cd2}', ['\u{2cd3}', '\u{0}', '\u{0}']),
+        ('\u{2cd4}', ['\u{2cd5}', '\u{0}', '\u{0}']), ('\u{2cd6}', ['\u{2cd7}', '\u{0}', '\u{0}']),
+        ('\u{2cd8}', ['\u{2cd9}', '\u{0}', '\u{0}']), ('\u{2cda}', ['\u{2cdb}', '\u{0}', '\u{0}']),
+        ('\u{2cdc}', ['\u{2cdd}', '\u{0}', '\u{0}']), ('\u{2cde}', ['\u{2cdf}', '\u{0}', '\u{0}']),
+        ('\u{2ce0}', ['\u{2ce1}', '\u{0}', '\u{0}']), ('\u{2ce2}', ['\u{2ce3}', '\u{0}', '\u{0}']),
+        ('\u{2ceb}', ['\u{2cec}', '\u{0}', '\u{0}']), ('\u{2ced}', ['\u{2cee}', '\u{0}', '\u{0}']),
+        ('\u{2cf2}', ['\u{2cf3}', '\u{0}', '\u{0}']), ('\u{a640}', ['\u{a641}', '\u{0}', '\u{0}']),
+        ('\u{a642}', ['\u{a643}', '\u{0}', '\u{0}']), ('\u{a644}', ['\u{a645}', '\u{0}', '\u{0}']),
+        ('\u{a646}', ['\u{a647}', '\u{0}', '\u{0}']), ('\u{a648}', ['\u{a649}', '\u{0}', '\u{0}']),
+        ('\u{a64a}', ['\u{a64b}', '\u{0}', '\u{0}']), ('\u{a64c}', ['\u{a64d}', '\u{0}', '\u{0}']),
+        ('\u{a64e}', ['\u{a64f}', '\u{0}', '\u{0}']), ('\u{a650}', ['\u{a651}', '\u{0}', '\u{0}']),
+        ('\u{a652}', ['\u{a653}', '\u{0}', '\u{0}']), ('\u{a654}', ['\u{a655}', '\u{0}', '\u{0}']),
+        ('\u{a656}', ['\u{a657}', '\u{0}', '\u{0}']), ('\u{a658}', ['\u{a659}', '\u{0}', '\u{0}']),
+        ('\u{a65a}', ['\u{a65b}', '\u{0}', '\u{0}']), ('\u{a65c}', ['\u{a65d}', '\u{0}', '\u{0}']),
+        ('\u{a65e}', ['\u{a65f}', '\u{0}', '\u{0}']), ('\u{a660}', ['\u{a661}', '\u{0}', '\u{0}']),
+        ('\u{a662}', ['\u{a663}', '\u{0}', '\u{0}']), ('\u{a664}', ['\u{a665}', '\u{0}', '\u{0}']),
+        ('\u{a666}', ['\u{a667}', '\u{0}', '\u{0}']), ('\u{a668}', ['\u{a669}', '\u{0}', '\u{0}']),
+        ('\u{a66a}', ['\u{a66b}', '\u{0}', '\u{0}']), ('\u{a66c}', ['\u{a66d}', '\u{0}', '\u{0}']),
+        ('\u{a680}', ['\u{a681}', '\u{0}', '\u{0}']), ('\u{a682}', ['\u{a683}', '\u{0}', '\u{0}']),
+        ('\u{a684}', ['\u{a685}', '\u{0}', '\u{0}']), ('\u{a686}', ['\u{a687}', '\u{0}', '\u{0}']),
+        ('\u{a688}', ['\u{a689}', '\u{0}', '\u{0}']), ('\u{a68a}', ['\u{a68b}', '\u{0}', '\u{0}']),
+        ('\u{a68c}', ['\u{a68d}', '\u{0}', '\u{0}']), ('\u{a68e}', ['\u{a68f}', '\u{0}', '\u{0}']),
+        ('\u{a690}', ['\u{a691}', '\u{0}', '\u{0}']), ('\u{a692}', ['\u{a693}', '\u{0}', '\u{0}']),
+        ('\u{a694}', ['\u{a695}', '\u{0}', '\u{0}']), ('\u{a696}', ['\u{a697}', '\u{0}', '\u{0}']),
+        ('\u{a698}', ['\u{a699}', '\u{0}', '\u{0}']), ('\u{a69a}', ['\u{a69b}', '\u{0}', '\u{0}']),
+        ('\u{a722}', ['\u{a723}', '\u{0}', '\u{0}']), ('\u{a724}', ['\u{a725}', '\u{0}', '\u{0}']),
+        ('\u{a726}', ['\u{a727}', '\u{0}', '\u{0}']), ('\u{a728}', ['\u{a729}', '\u{0}', '\u{0}']),
+        ('\u{a72a}', ['\u{a72b}', '\u{0}', '\u{0}']), ('\u{a72c}', ['\u{a72d}', '\u{0}', '\u{0}']),
+        ('\u{a72e}', ['\u{a72f}', '\u{0}', '\u{0}']), ('\u{a732}', ['\u{a733}', '\u{0}', '\u{0}']),
+        ('\u{a734}', ['\u{a735}', '\u{0}', '\u{0}']), ('\u{a736}', ['\u{a737}', '\u{0}', '\u{0}']),
+        ('\u{a738}', ['\u{a739}', '\u{0}', '\u{0}']), ('\u{a73a}', ['\u{a73b}', '\u{0}', '\u{0}']),
+        ('\u{a73c}', ['\u{a73d}', '\u{0}', '\u{0}']), ('\u{a73e}', ['\u{a73f}', '\u{0}', '\u{0}']),
+        ('\u{a740}', ['\u{a741}', '\u{0}', '\u{0}']), ('\u{a742}', ['\u{a743}', '\u{0}', '\u{0}']),
+        ('\u{a744}', ['\u{a745}', '\u{0}', '\u{0}']), ('\u{a746}', ['\u{a747}', '\u{0}', '\u{0}']),
+        ('\u{a748}', ['\u{a749}', '\u{0}', '\u{0}']), ('\u{a74a}', ['\u{a74b}', '\u{0}', '\u{0}']),
+        ('\u{a74c}', ['\u{a74d}', '\u{0}', '\u{0}']), ('\u{a74e}', ['\u{a74f}', '\u{0}', '\u{0}']),
+        ('\u{a750}', ['\u{a751}', '\u{0}', '\u{0}']), ('\u{a752}', ['\u{a753}', '\u{0}', '\u{0}']),
+        ('\u{a754}', ['\u{a755}', '\u{0}', '\u{0}']), ('\u{a756}', ['\u{a757}', '\u{0}', '\u{0}']),
+        ('\u{a758}', ['\u{a759}', '\u{0}', '\u{0}']), ('\u{a75a}', ['\u{a75b}', '\u{0}', '\u{0}']),
+        ('\u{a75c}', ['\u{a75d}', '\u{0}', '\u{0}']), ('\u{a75e}', ['\u{a75f}', '\u{0}', '\u{0}']),
+        ('\u{a760}', ['\u{a761}', '\u{0}', '\u{0}']), ('\u{a762}', ['\u{a763}', '\u{0}', '\u{0}']),
+        ('\u{a764}', ['\u{a765}', '\u{0}', '\u{0}']), ('\u{a766}', ['\u{a767}', '\u{0}', '\u{0}']),
+        ('\u{a768}', ['\u{a769}', '\u{0}', '\u{0}']), ('\u{a76a}', ['\u{a76b}', '\u{0}', '\u{0}']),
+        ('\u{a76c}', ['\u{a76d}', '\u{0}', '\u{0}']), ('\u{a76e}', ['\u{a76f}', '\u{0}', '\u{0}']),
+        ('\u{a779}', ['\u{a77a}', '\u{0}', '\u{0}']), ('\u{a77b}', ['\u{a77c}', '\u{0}', '\u{0}']),
+        ('\u{a77d}', ['\u{1d79}', '\u{0}', '\u{0}']), ('\u{a77e}', ['\u{a77f}', '\u{0}', '\u{0}']),
+        ('\u{a780}', ['\u{a781}', '\u{0}', '\u{0}']), ('\u{a782}', ['\u{a783}', '\u{0}', '\u{0}']),
+        ('\u{a784}', ['\u{a785}', '\u{0}', '\u{0}']), ('\u{a786}', ['\u{a787}', '\u{0}', '\u{0}']),
+        ('\u{a78b}', ['\u{a78c}', '\u{0}', '\u{0}']), ('\u{a78d}', ['\u{265}', '\u{0}', '\u{0}']),
+        ('\u{a790}', ['\u{a791}', '\u{0}', '\u{0}']), ('\u{a792}', ['\u{a793}', '\u{0}', '\u{0}']),
+        ('\u{a796}', ['\u{a797}', '\u{0}', '\u{0}']), ('\u{a798}', ['\u{a799}', '\u{0}', '\u{0}']),
+        ('\u{a79a}', ['\u{a79b}', '\u{0}', '\u{0}']), ('\u{a79c}', ['\u{a79d}', '\u{0}', '\u{0}']),
+        ('\u{a79e}', ['\u{a79f}', '\u{0}', '\u{0}']), ('\u{a7a0}', ['\u{a7a1}', '\u{0}', '\u{0}']),
+        ('\u{a7a2}', ['\u{a7a3}', '\u{0}', '\u{0}']), ('\u{a7a4}', ['\u{a7a5}', '\u{0}', '\u{0}']),
+        ('\u{a7a6}', ['\u{a7a7}', '\u{0}', '\u{0}']), ('\u{a7a8}', ['\u{a7a9}', '\u{0}', '\u{0}']),
+        ('\u{a7aa}', ['\u{266}', '\u{0}', '\u{0}']), ('\u{a7ab}', ['\u{25c}', '\u{0}', '\u{0}']),
+        ('\u{a7ac}', ['\u{261}', '\u{0}', '\u{0}']), ('\u{a7ad}', ['\u{26c}', '\u{0}', '\u{0}']),
+        ('\u{a7ae}', ['\u{26a}', '\u{0}', '\u{0}']), ('\u{a7b0}', ['\u{29e}', '\u{0}', '\u{0}']),
+        ('\u{a7b1}', ['\u{287}', '\u{0}', '\u{0}']), ('\u{a7b2}', ['\u{29d}', '\u{0}', '\u{0}']),
+        ('\u{a7b3}', ['\u{ab53}', '\u{0}', '\u{0}']), ('\u{a7b4}', ['\u{a7b5}', '\u{0}', '\u{0}']),
+        ('\u{a7b6}', ['\u{a7b7}', '\u{0}', '\u{0}']), ('\u{a7b8}', ['\u{a7b9}', '\u{0}', '\u{0}']),
+        ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']),
+        ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']),
+        ('\u{a7c4}', ['\u{a794}', '\u{0}', '\u{0}']), ('\u{a7c5}', ['\u{282}', '\u{0}', '\u{0}']),
+        ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']),
+        ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']),
+        ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']),
+        ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']),
+        ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']),
+        ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']),
+        ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']),
+        ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']),
+        ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']),
+        ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']),
+        ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']),
+        ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']),
+        ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']),
+        ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']),
+        ('\u{10400}', ['\u{10428}', '\u{0}', '\u{0}']),
+        ('\u{10401}', ['\u{10429}', '\u{0}', '\u{0}']),
+        ('\u{10402}', ['\u{1042a}', '\u{0}', '\u{0}']),
+        ('\u{10403}', ['\u{1042b}', '\u{0}', '\u{0}']),
+        ('\u{10404}', ['\u{1042c}', '\u{0}', '\u{0}']),
+        ('\u{10405}', ['\u{1042d}', '\u{0}', '\u{0}']),
+        ('\u{10406}', ['\u{1042e}', '\u{0}', '\u{0}']),
+        ('\u{10407}', ['\u{1042f}', '\u{0}', '\u{0}']),
+        ('\u{10408}', ['\u{10430}', '\u{0}', '\u{0}']),
+        ('\u{10409}', ['\u{10431}', '\u{0}', '\u{0}']),
+        ('\u{1040a}', ['\u{10432}', '\u{0}', '\u{0}']),
+        ('\u{1040b}', ['\u{10433}', '\u{0}', '\u{0}']),
+        ('\u{1040c}', ['\u{10434}', '\u{0}', '\u{0}']),
+        ('\u{1040d}', ['\u{10435}', '\u{0}', '\u{0}']),
+        ('\u{1040e}', ['\u{10436}', '\u{0}', '\u{0}']),
+        ('\u{1040f}', ['\u{10437}', '\u{0}', '\u{0}']),
+        ('\u{10410}', ['\u{10438}', '\u{0}', '\u{0}']),
+        ('\u{10411}', ['\u{10439}', '\u{0}', '\u{0}']),
+        ('\u{10412}', ['\u{1043a}', '\u{0}', '\u{0}']),
+        ('\u{10413}', ['\u{1043b}', '\u{0}', '\u{0}']),
+        ('\u{10414}', ['\u{1043c}', '\u{0}', '\u{0}']),
+        ('\u{10415}', ['\u{1043d}', '\u{0}', '\u{0}']),
+        ('\u{10416}', ['\u{1043e}', '\u{0}', '\u{0}']),
+        ('\u{10417}', ['\u{1043f}', '\u{0}', '\u{0}']),
+        ('\u{10418}', ['\u{10440}', '\u{0}', '\u{0}']),
+        ('\u{10419}', ['\u{10441}', '\u{0}', '\u{0}']),
+        ('\u{1041a}', ['\u{10442}', '\u{0}', '\u{0}']),
+        ('\u{1041b}', ['\u{10443}', '\u{0}', '\u{0}']),
+        ('\u{1041c}', ['\u{10444}', '\u{0}', '\u{0}']),
+        ('\u{1041d}', ['\u{10445}', '\u{0}', '\u{0}']),
+        ('\u{1041e}', ['\u{10446}', '\u{0}', '\u{0}']),
+        ('\u{1041f}', ['\u{10447}', '\u{0}', '\u{0}']),
+        ('\u{10420}', ['\u{10448}', '\u{0}', '\u{0}']),
+        ('\u{10421}', ['\u{10449}', '\u{0}', '\u{0}']),
+        ('\u{10422}', ['\u{1044a}', '\u{0}', '\u{0}']),
+        ('\u{10423}', ['\u{1044b}', '\u{0}', '\u{0}']),
+        ('\u{10424}', ['\u{1044c}', '\u{0}', '\u{0}']),
+        ('\u{10425}', ['\u{1044d}', '\u{0}', '\u{0}']),
+        ('\u{10426}', ['\u{1044e}', '\u{0}', '\u{0}']),
+        ('\u{10427}', ['\u{1044f}', '\u{0}', '\u{0}']),
+        ('\u{104b0}', ['\u{104d8}', '\u{0}', '\u{0}']),
+        ('\u{104b1}', ['\u{104d9}', '\u{0}', '\u{0}']),
+        ('\u{104b2}', ['\u{104da}', '\u{0}', '\u{0}']),
+        ('\u{104b3}', ['\u{104db}', '\u{0}', '\u{0}']),
+        ('\u{104b4}', ['\u{104dc}', '\u{0}', '\u{0}']),
+        ('\u{104b5}', ['\u{104dd}', '\u{0}', '\u{0}']),
+        ('\u{104b6}', ['\u{104de}', '\u{0}', '\u{0}']),
+        ('\u{104b7}', ['\u{104df}', '\u{0}', '\u{0}']),
+        ('\u{104b8}', ['\u{104e0}', '\u{0}', '\u{0}']),
+        ('\u{104b9}', ['\u{104e1}', '\u{0}', '\u{0}']),
+        ('\u{104ba}', ['\u{104e2}', '\u{0}', '\u{0}']),
+        ('\u{104bb}', ['\u{104e3}', '\u{0}', '\u{0}']),
+        ('\u{104bc}', ['\u{104e4}', '\u{0}', '\u{0}']),
+        ('\u{104bd}', ['\u{104e5}', '\u{0}', '\u{0}']),
+        ('\u{104be}', ['\u{104e6}', '\u{0}', '\u{0}']),
+        ('\u{104bf}', ['\u{104e7}', '\u{0}', '\u{0}']),
+        ('\u{104c0}', ['\u{104e8}', '\u{0}', '\u{0}']),
+        ('\u{104c1}', ['\u{104e9}', '\u{0}', '\u{0}']),
+        ('\u{104c2}', ['\u{104ea}', '\u{0}', '\u{0}']),
+        ('\u{104c3}', ['\u{104eb}', '\u{0}', '\u{0}']),
+        ('\u{104c4}', ['\u{104ec}', '\u{0}', '\u{0}']),
+        ('\u{104c5}', ['\u{104ed}', '\u{0}', '\u{0}']),
+        ('\u{104c6}', ['\u{104ee}', '\u{0}', '\u{0}']),
+        ('\u{104c7}', ['\u{104ef}', '\u{0}', '\u{0}']),
+        ('\u{104c8}', ['\u{104f0}', '\u{0}', '\u{0}']),
+        ('\u{104c9}', ['\u{104f1}', '\u{0}', '\u{0}']),
+        ('\u{104ca}', ['\u{104f2}', '\u{0}', '\u{0}']),
+        ('\u{104cb}', ['\u{104f3}', '\u{0}', '\u{0}']),
+        ('\u{104cc}', ['\u{104f4}', '\u{0}', '\u{0}']),
+        ('\u{104cd}', ['\u{104f5}', '\u{0}', '\u{0}']),
+        ('\u{104ce}', ['\u{104f6}', '\u{0}', '\u{0}']),
+        ('\u{104cf}', ['\u{104f7}', '\u{0}', '\u{0}']),
+        ('\u{104d0}', ['\u{104f8}', '\u{0}', '\u{0}']),
+        ('\u{104d1}', ['\u{104f9}', '\u{0}', '\u{0}']),
+        ('\u{104d2}', ['\u{104fa}', '\u{0}', '\u{0}']),
+        ('\u{104d3}', ['\u{104fb}', '\u{0}', '\u{0}']),
+        ('\u{10c80}', ['\u{10cc0}', '\u{0}', '\u{0}']),
+        ('\u{10c81}', ['\u{10cc1}', '\u{0}', '\u{0}']),
+        ('\u{10c82}', ['\u{10cc2}', '\u{0}', '\u{0}']),
+        ('\u{10c83}', ['\u{10cc3}', '\u{0}', '\u{0}']),
+        ('\u{10c84}', ['\u{10cc4}', '\u{0}', '\u{0}']),
+        ('\u{10c85}', ['\u{10cc5}', '\u{0}', '\u{0}']),
+        ('\u{10c86}', ['\u{10cc6}', '\u{0}', '\u{0}']),
+        ('\u{10c87}', ['\u{10cc7}', '\u{0}', '\u{0}']),
+        ('\u{10c88}', ['\u{10cc8}', '\u{0}', '\u{0}']),
+        ('\u{10c89}', ['\u{10cc9}', '\u{0}', '\u{0}']),
+        ('\u{10c8a}', ['\u{10cca}', '\u{0}', '\u{0}']),
+        ('\u{10c8b}', ['\u{10ccb}', '\u{0}', '\u{0}']),
+        ('\u{10c8c}', ['\u{10ccc}', '\u{0}', '\u{0}']),
+        ('\u{10c8d}', ['\u{10ccd}', '\u{0}', '\u{0}']),
+        ('\u{10c8e}', ['\u{10cce}', '\u{0}', '\u{0}']),
+        ('\u{10c8f}', ['\u{10ccf}', '\u{0}', '\u{0}']),
+        ('\u{10c90}', ['\u{10cd0}', '\u{0}', '\u{0}']),
+        ('\u{10c91}', ['\u{10cd1}', '\u{0}', '\u{0}']),
+        ('\u{10c92}', ['\u{10cd2}', '\u{0}', '\u{0}']),
+        ('\u{10c93}', ['\u{10cd3}', '\u{0}', '\u{0}']),
+        ('\u{10c94}', ['\u{10cd4}', '\u{0}', '\u{0}']),
+        ('\u{10c95}', ['\u{10cd5}', '\u{0}', '\u{0}']),
+        ('\u{10c96}', ['\u{10cd6}', '\u{0}', '\u{0}']),
+        ('\u{10c97}', ['\u{10cd7}', '\u{0}', '\u{0}']),
+        ('\u{10c98}', ['\u{10cd8}', '\u{0}', '\u{0}']),
+        ('\u{10c99}', ['\u{10cd9}', '\u{0}', '\u{0}']),
+        ('\u{10c9a}', ['\u{10cda}', '\u{0}', '\u{0}']),
+        ('\u{10c9b}', ['\u{10cdb}', '\u{0}', '\u{0}']),
+        ('\u{10c9c}', ['\u{10cdc}', '\u{0}', '\u{0}']),
+        ('\u{10c9d}', ['\u{10cdd}', '\u{0}', '\u{0}']),
+        ('\u{10c9e}', ['\u{10cde}', '\u{0}', '\u{0}']),
+        ('\u{10c9f}', ['\u{10cdf}', '\u{0}', '\u{0}']),
+        ('\u{10ca0}', ['\u{10ce0}', '\u{0}', '\u{0}']),
+        ('\u{10ca1}', ['\u{10ce1}', '\u{0}', '\u{0}']),
+        ('\u{10ca2}', ['\u{10ce2}', '\u{0}', '\u{0}']),
+        ('\u{10ca3}', ['\u{10ce3}', '\u{0}', '\u{0}']),
+        ('\u{10ca4}', ['\u{10ce4}', '\u{0}', '\u{0}']),
+        ('\u{10ca5}', ['\u{10ce5}', '\u{0}', '\u{0}']),
+        ('\u{10ca6}', ['\u{10ce6}', '\u{0}', '\u{0}']),
+        ('\u{10ca7}', ['\u{10ce7}', '\u{0}', '\u{0}']),
+        ('\u{10ca8}', ['\u{10ce8}', '\u{0}', '\u{0}']),
+        ('\u{10ca9}', ['\u{10ce9}', '\u{0}', '\u{0}']),
+        ('\u{10caa}', ['\u{10cea}', '\u{0}', '\u{0}']),
+        ('\u{10cab}', ['\u{10ceb}', '\u{0}', '\u{0}']),
+        ('\u{10cac}', ['\u{10cec}', '\u{0}', '\u{0}']),
+        ('\u{10cad}', ['\u{10ced}', '\u{0}', '\u{0}']),
+        ('\u{10cae}', ['\u{10cee}', '\u{0}', '\u{0}']),
+        ('\u{10caf}', ['\u{10cef}', '\u{0}', '\u{0}']),
+        ('\u{10cb0}', ['\u{10cf0}', '\u{0}', '\u{0}']),
+        ('\u{10cb1}', ['\u{10cf1}', '\u{0}', '\u{0}']),
+        ('\u{10cb2}', ['\u{10cf2}', '\u{0}', '\u{0}']),
+        ('\u{118a0}', ['\u{118c0}', '\u{0}', '\u{0}']),
+        ('\u{118a1}', ['\u{118c1}', '\u{0}', '\u{0}']),
+        ('\u{118a2}', ['\u{118c2}', '\u{0}', '\u{0}']),
+        ('\u{118a3}', ['\u{118c3}', '\u{0}', '\u{0}']),
+        ('\u{118a4}', ['\u{118c4}', '\u{0}', '\u{0}']),
+        ('\u{118a5}', ['\u{118c5}', '\u{0}', '\u{0}']),
+        ('\u{118a6}', ['\u{118c6}', '\u{0}', '\u{0}']),
+        ('\u{118a7}', ['\u{118c7}', '\u{0}', '\u{0}']),
+        ('\u{118a8}', ['\u{118c8}', '\u{0}', '\u{0}']),
+        ('\u{118a9}', ['\u{118c9}', '\u{0}', '\u{0}']),
+        ('\u{118aa}', ['\u{118ca}', '\u{0}', '\u{0}']),
+        ('\u{118ab}', ['\u{118cb}', '\u{0}', '\u{0}']),
+        ('\u{118ac}', ['\u{118cc}', '\u{0}', '\u{0}']),
+        ('\u{118ad}', ['\u{118cd}', '\u{0}', '\u{0}']),
+        ('\u{118ae}', ['\u{118ce}', '\u{0}', '\u{0}']),
+        ('\u{118af}', ['\u{118cf}', '\u{0}', '\u{0}']),
+        ('\u{118b0}', ['\u{118d0}', '\u{0}', '\u{0}']),
+        ('\u{118b1}', ['\u{118d1}', '\u{0}', '\u{0}']),
+        ('\u{118b2}', ['\u{118d2}', '\u{0}', '\u{0}']),
+        ('\u{118b3}', ['\u{118d3}', '\u{0}', '\u{0}']),
+        ('\u{118b4}', ['\u{118d4}', '\u{0}', '\u{0}']),
+        ('\u{118b5}', ['\u{118d5}', '\u{0}', '\u{0}']),
+        ('\u{118b6}', ['\u{118d6}', '\u{0}', '\u{0}']),
+        ('\u{118b7}', ['\u{118d7}', '\u{0}', '\u{0}']),
+        ('\u{118b8}', ['\u{118d8}', '\u{0}', '\u{0}']),
+        ('\u{118b9}', ['\u{118d9}', '\u{0}', '\u{0}']),
+        ('\u{118ba}', ['\u{118da}', '\u{0}', '\u{0}']),
+        ('\u{118bb}', ['\u{118db}', '\u{0}', '\u{0}']),
+        ('\u{118bc}', ['\u{118dc}', '\u{0}', '\u{0}']),
+        ('\u{118bd}', ['\u{118dd}', '\u{0}', '\u{0}']),
+        ('\u{118be}', ['\u{118de}', '\u{0}', '\u{0}']),
+        ('\u{118bf}', ['\u{118df}', '\u{0}', '\u{0}']),
+        ('\u{16e40}', ['\u{16e60}', '\u{0}', '\u{0}']),
+        ('\u{16e41}', ['\u{16e61}', '\u{0}', '\u{0}']),
+        ('\u{16e42}', ['\u{16e62}', '\u{0}', '\u{0}']),
+        ('\u{16e43}', ['\u{16e63}', '\u{0}', '\u{0}']),
+        ('\u{16e44}', ['\u{16e64}', '\u{0}', '\u{0}']),
+        ('\u{16e45}', ['\u{16e65}', '\u{0}', '\u{0}']),
+        ('\u{16e46}', ['\u{16e66}', '\u{0}', '\u{0}']),
+        ('\u{16e47}', ['\u{16e67}', '\u{0}', '\u{0}']),
+        ('\u{16e48}', ['\u{16e68}', '\u{0}', '\u{0}']),
+        ('\u{16e49}', ['\u{16e69}', '\u{0}', '\u{0}']),
+        ('\u{16e4a}', ['\u{16e6a}', '\u{0}', '\u{0}']),
+        ('\u{16e4b}', ['\u{16e6b}', '\u{0}', '\u{0}']),
+        ('\u{16e4c}', ['\u{16e6c}', '\u{0}', '\u{0}']),
+        ('\u{16e4d}', ['\u{16e6d}', '\u{0}', '\u{0}']),
+        ('\u{16e4e}', ['\u{16e6e}', '\u{0}', '\u{0}']),
+        ('\u{16e4f}', ['\u{16e6f}', '\u{0}', '\u{0}']),
+        ('\u{16e50}', ['\u{16e70}', '\u{0}', '\u{0}']),
+        ('\u{16e51}', ['\u{16e71}', '\u{0}', '\u{0}']),
+        ('\u{16e52}', ['\u{16e72}', '\u{0}', '\u{0}']),
+        ('\u{16e53}', ['\u{16e73}', '\u{0}', '\u{0}']),
+        ('\u{16e54}', ['\u{16e74}', '\u{0}', '\u{0}']),
+        ('\u{16e55}', ['\u{16e75}', '\u{0}', '\u{0}']),
+        ('\u{16e56}', ['\u{16e76}', '\u{0}', '\u{0}']),
+        ('\u{16e57}', ['\u{16e77}', '\u{0}', '\u{0}']),
+        ('\u{16e58}', ['\u{16e78}', '\u{0}', '\u{0}']),
+        ('\u{16e59}', ['\u{16e79}', '\u{0}', '\u{0}']),
+        ('\u{16e5a}', ['\u{16e7a}', '\u{0}', '\u{0}']),
+        ('\u{16e5b}', ['\u{16e7b}', '\u{0}', '\u{0}']),
+        ('\u{16e5c}', ['\u{16e7c}', '\u{0}', '\u{0}']),
+        ('\u{16e5d}', ['\u{16e7d}', '\u{0}', '\u{0}']),
+        ('\u{16e5e}', ['\u{16e7e}', '\u{0}', '\u{0}']),
+        ('\u{16e5f}', ['\u{16e7f}', '\u{0}', '\u{0}']),
+        ('\u{1e900}', ['\u{1e922}', '\u{0}', '\u{0}']),
+        ('\u{1e901}', ['\u{1e923}', '\u{0}', '\u{0}']),
+        ('\u{1e902}', ['\u{1e924}', '\u{0}', '\u{0}']),
+        ('\u{1e903}', ['\u{1e925}', '\u{0}', '\u{0}']),
+        ('\u{1e904}', ['\u{1e926}', '\u{0}', '\u{0}']),
+        ('\u{1e905}', ['\u{1e927}', '\u{0}', '\u{0}']),
+        ('\u{1e906}', ['\u{1e928}', '\u{0}', '\u{0}']),
+        ('\u{1e907}', ['\u{1e929}', '\u{0}', '\u{0}']),
+        ('\u{1e908}', ['\u{1e92a}', '\u{0}', '\u{0}']),
+        ('\u{1e909}', ['\u{1e92b}', '\u{0}', '\u{0}']),
+        ('\u{1e90a}', ['\u{1e92c}', '\u{0}', '\u{0}']),
+        ('\u{1e90b}', ['\u{1e92d}', '\u{0}', '\u{0}']),
+        ('\u{1e90c}', ['\u{1e92e}', '\u{0}', '\u{0}']),
+        ('\u{1e90d}', ['\u{1e92f}', '\u{0}', '\u{0}']),
+        ('\u{1e90e}', ['\u{1e930}', '\u{0}', '\u{0}']),
+        ('\u{1e90f}', ['\u{1e931}', '\u{0}', '\u{0}']),
+        ('\u{1e910}', ['\u{1e932}', '\u{0}', '\u{0}']),
+        ('\u{1e911}', ['\u{1e933}', '\u{0}', '\u{0}']),
+        ('\u{1e912}', ['\u{1e934}', '\u{0}', '\u{0}']),
+        ('\u{1e913}', ['\u{1e935}', '\u{0}', '\u{0}']),
+        ('\u{1e914}', ['\u{1e936}', '\u{0}', '\u{0}']),
+        ('\u{1e915}', ['\u{1e937}', '\u{0}', '\u{0}']),
+        ('\u{1e916}', ['\u{1e938}', '\u{0}', '\u{0}']),
+        ('\u{1e917}', ['\u{1e939}', '\u{0}', '\u{0}']),
+        ('\u{1e918}', ['\u{1e93a}', '\u{0}', '\u{0}']),
+        ('\u{1e919}', ['\u{1e93b}', '\u{0}', '\u{0}']),
+        ('\u{1e91a}', ['\u{1e93c}', '\u{0}', '\u{0}']),
+        ('\u{1e91b}', ['\u{1e93d}', '\u{0}', '\u{0}']),
+        ('\u{1e91c}', ['\u{1e93e}', '\u{0}', '\u{0}']),
+        ('\u{1e91d}', ['\u{1e93f}', '\u{0}', '\u{0}']),
+        ('\u{1e91e}', ['\u{1e940}', '\u{0}', '\u{0}']),
+        ('\u{1e91f}', ['\u{1e941}', '\u{0}', '\u{0}']),
+        ('\u{1e920}', ['\u{1e942}', '\u{0}', '\u{0}']),
+        ('\u{1e921}', ['\u{1e943}', '\u{0}', '\u{0}']),
+    ];
+
+    static UPPERCASE_TABLE: &[(char, [char; 3])] = &[
+        ('a', ['A', '\u{0}', '\u{0}']), ('b', ['B', '\u{0}', '\u{0}']),
+        ('c', ['C', '\u{0}', '\u{0}']), ('d', ['D', '\u{0}', '\u{0}']),
+        ('e', ['E', '\u{0}', '\u{0}']), ('f', ['F', '\u{0}', '\u{0}']),
+        ('g', ['G', '\u{0}', '\u{0}']), ('h', ['H', '\u{0}', '\u{0}']),
+        ('i', ['I', '\u{0}', '\u{0}']), ('j', ['J', '\u{0}', '\u{0}']),
+        ('k', ['K', '\u{0}', '\u{0}']), ('l', ['L', '\u{0}', '\u{0}']),
+        ('m', ['M', '\u{0}', '\u{0}']), ('n', ['N', '\u{0}', '\u{0}']),
+        ('o', ['O', '\u{0}', '\u{0}']), ('p', ['P', '\u{0}', '\u{0}']),
+        ('q', ['Q', '\u{0}', '\u{0}']), ('r', ['R', '\u{0}', '\u{0}']),
+        ('s', ['S', '\u{0}', '\u{0}']), ('t', ['T', '\u{0}', '\u{0}']),
+        ('u', ['U', '\u{0}', '\u{0}']), ('v', ['V', '\u{0}', '\u{0}']),
+        ('w', ['W', '\u{0}', '\u{0}']), ('x', ['X', '\u{0}', '\u{0}']),
+        ('y', ['Y', '\u{0}', '\u{0}']), ('z', ['Z', '\u{0}', '\u{0}']),
+        ('\u{b5}', ['\u{39c}', '\u{0}', '\u{0}']), ('\u{df}', ['S', 'S', '\u{0}']),
+        ('\u{e0}', ['\u{c0}', '\u{0}', '\u{0}']), ('\u{e1}', ['\u{c1}', '\u{0}', '\u{0}']),
+        ('\u{e2}', ['\u{c2}', '\u{0}', '\u{0}']), ('\u{e3}', ['\u{c3}', '\u{0}', '\u{0}']),
+        ('\u{e4}', ['\u{c4}', '\u{0}', '\u{0}']), ('\u{e5}', ['\u{c5}', '\u{0}', '\u{0}']),
+        ('\u{e6}', ['\u{c6}', '\u{0}', '\u{0}']), ('\u{e7}', ['\u{c7}', '\u{0}', '\u{0}']),
+        ('\u{e8}', ['\u{c8}', '\u{0}', '\u{0}']), ('\u{e9}', ['\u{c9}', '\u{0}', '\u{0}']),
+        ('\u{ea}', ['\u{ca}', '\u{0}', '\u{0}']), ('\u{eb}', ['\u{cb}', '\u{0}', '\u{0}']),
+        ('\u{ec}', ['\u{cc}', '\u{0}', '\u{0}']), ('\u{ed}', ['\u{cd}', '\u{0}', '\u{0}']),
+        ('\u{ee}', ['\u{ce}', '\u{0}', '\u{0}']), ('\u{ef}', ['\u{cf}', '\u{0}', '\u{0}']),
+        ('\u{f0}', ['\u{d0}', '\u{0}', '\u{0}']), ('\u{f1}', ['\u{d1}', '\u{0}', '\u{0}']),
+        ('\u{f2}', ['\u{d2}', '\u{0}', '\u{0}']), ('\u{f3}', ['\u{d3}', '\u{0}', '\u{0}']),
+        ('\u{f4}', ['\u{d4}', '\u{0}', '\u{0}']), ('\u{f5}', ['\u{d5}', '\u{0}', '\u{0}']),
+        ('\u{f6}', ['\u{d6}', '\u{0}', '\u{0}']), ('\u{f8}', ['\u{d8}', '\u{0}', '\u{0}']),
+        ('\u{f9}', ['\u{d9}', '\u{0}', '\u{0}']), ('\u{fa}', ['\u{da}', '\u{0}', '\u{0}']),
+        ('\u{fb}', ['\u{db}', '\u{0}', '\u{0}']), ('\u{fc}', ['\u{dc}', '\u{0}', '\u{0}']),
+        ('\u{fd}', ['\u{dd}', '\u{0}', '\u{0}']), ('\u{fe}', ['\u{de}', '\u{0}', '\u{0}']),
+        ('\u{ff}', ['\u{178}', '\u{0}', '\u{0}']), ('\u{101}', ['\u{100}', '\u{0}', '\u{0}']),
+        ('\u{103}', ['\u{102}', '\u{0}', '\u{0}']), ('\u{105}', ['\u{104}', '\u{0}', '\u{0}']),
+        ('\u{107}', ['\u{106}', '\u{0}', '\u{0}']), ('\u{109}', ['\u{108}', '\u{0}', '\u{0}']),
+        ('\u{10b}', ['\u{10a}', '\u{0}', '\u{0}']), ('\u{10d}', ['\u{10c}', '\u{0}', '\u{0}']),
+        ('\u{10f}', ['\u{10e}', '\u{0}', '\u{0}']), ('\u{111}', ['\u{110}', '\u{0}', '\u{0}']),
+        ('\u{113}', ['\u{112}', '\u{0}', '\u{0}']), ('\u{115}', ['\u{114}', '\u{0}', '\u{0}']),
+        ('\u{117}', ['\u{116}', '\u{0}', '\u{0}']), ('\u{119}', ['\u{118}', '\u{0}', '\u{0}']),
+        ('\u{11b}', ['\u{11a}', '\u{0}', '\u{0}']), ('\u{11d}', ['\u{11c}', '\u{0}', '\u{0}']),
+        ('\u{11f}', ['\u{11e}', '\u{0}', '\u{0}']), ('\u{121}', ['\u{120}', '\u{0}', '\u{0}']),
+        ('\u{123}', ['\u{122}', '\u{0}', '\u{0}']), ('\u{125}', ['\u{124}', '\u{0}', '\u{0}']),
+        ('\u{127}', ['\u{126}', '\u{0}', '\u{0}']), ('\u{129}', ['\u{128}', '\u{0}', '\u{0}']),
+        ('\u{12b}', ['\u{12a}', '\u{0}', '\u{0}']), ('\u{12d}', ['\u{12c}', '\u{0}', '\u{0}']),
+        ('\u{12f}', ['\u{12e}', '\u{0}', '\u{0}']), ('\u{131}', ['I', '\u{0}', '\u{0}']),
+        ('\u{133}', ['\u{132}', '\u{0}', '\u{0}']), ('\u{135}', ['\u{134}', '\u{0}', '\u{0}']),
+        ('\u{137}', ['\u{136}', '\u{0}', '\u{0}']), ('\u{13a}', ['\u{139}', '\u{0}', '\u{0}']),
+        ('\u{13c}', ['\u{13b}', '\u{0}', '\u{0}']), ('\u{13e}', ['\u{13d}', '\u{0}', '\u{0}']),
+        ('\u{140}', ['\u{13f}', '\u{0}', '\u{0}']), ('\u{142}', ['\u{141}', '\u{0}', '\u{0}']),
+        ('\u{144}', ['\u{143}', '\u{0}', '\u{0}']), ('\u{146}', ['\u{145}', '\u{0}', '\u{0}']),
+        ('\u{148}', ['\u{147}', '\u{0}', '\u{0}']), ('\u{149}', ['\u{2bc}', 'N', '\u{0}']),
+        ('\u{14b}', ['\u{14a}', '\u{0}', '\u{0}']), ('\u{14d}', ['\u{14c}', '\u{0}', '\u{0}']),
+        ('\u{14f}', ['\u{14e}', '\u{0}', '\u{0}']), ('\u{151}', ['\u{150}', '\u{0}', '\u{0}']),
+        ('\u{153}', ['\u{152}', '\u{0}', '\u{0}']), ('\u{155}', ['\u{154}', '\u{0}', '\u{0}']),
+        ('\u{157}', ['\u{156}', '\u{0}', '\u{0}']), ('\u{159}', ['\u{158}', '\u{0}', '\u{0}']),
+        ('\u{15b}', ['\u{15a}', '\u{0}', '\u{0}']), ('\u{15d}', ['\u{15c}', '\u{0}', '\u{0}']),
+        ('\u{15f}', ['\u{15e}', '\u{0}', '\u{0}']), ('\u{161}', ['\u{160}', '\u{0}', '\u{0}']),
+        ('\u{163}', ['\u{162}', '\u{0}', '\u{0}']), ('\u{165}', ['\u{164}', '\u{0}', '\u{0}']),
+        ('\u{167}', ['\u{166}', '\u{0}', '\u{0}']), ('\u{169}', ['\u{168}', '\u{0}', '\u{0}']),
+        ('\u{16b}', ['\u{16a}', '\u{0}', '\u{0}']), ('\u{16d}', ['\u{16c}', '\u{0}', '\u{0}']),
+        ('\u{16f}', ['\u{16e}', '\u{0}', '\u{0}']), ('\u{171}', ['\u{170}', '\u{0}', '\u{0}']),
+        ('\u{173}', ['\u{172}', '\u{0}', '\u{0}']), ('\u{175}', ['\u{174}', '\u{0}', '\u{0}']),
+        ('\u{177}', ['\u{176}', '\u{0}', '\u{0}']), ('\u{17a}', ['\u{179}', '\u{0}', '\u{0}']),
+        ('\u{17c}', ['\u{17b}', '\u{0}', '\u{0}']), ('\u{17e}', ['\u{17d}', '\u{0}', '\u{0}']),
+        ('\u{17f}', ['S', '\u{0}', '\u{0}']), ('\u{180}', ['\u{243}', '\u{0}', '\u{0}']),
+        ('\u{183}', ['\u{182}', '\u{0}', '\u{0}']), ('\u{185}', ['\u{184}', '\u{0}', '\u{0}']),
+        ('\u{188}', ['\u{187}', '\u{0}', '\u{0}']), ('\u{18c}', ['\u{18b}', '\u{0}', '\u{0}']),
+        ('\u{192}', ['\u{191}', '\u{0}', '\u{0}']), ('\u{195}', ['\u{1f6}', '\u{0}', '\u{0}']),
+        ('\u{199}', ['\u{198}', '\u{0}', '\u{0}']), ('\u{19a}', ['\u{23d}', '\u{0}', '\u{0}']),
+        ('\u{19e}', ['\u{220}', '\u{0}', '\u{0}']), ('\u{1a1}', ['\u{1a0}', '\u{0}', '\u{0}']),
+        ('\u{1a3}', ['\u{1a2}', '\u{0}', '\u{0}']), ('\u{1a5}', ['\u{1a4}', '\u{0}', '\u{0}']),
+        ('\u{1a8}', ['\u{1a7}', '\u{0}', '\u{0}']), ('\u{1ad}', ['\u{1ac}', '\u{0}', '\u{0}']),
+        ('\u{1b0}', ['\u{1af}', '\u{0}', '\u{0}']), ('\u{1b4}', ['\u{1b3}', '\u{0}', '\u{0}']),
+        ('\u{1b6}', ['\u{1b5}', '\u{0}', '\u{0}']), ('\u{1b9}', ['\u{1b8}', '\u{0}', '\u{0}']),
+        ('\u{1bd}', ['\u{1bc}', '\u{0}', '\u{0}']), ('\u{1bf}', ['\u{1f7}', '\u{0}', '\u{0}']),
+        ('\u{1c5}', ['\u{1c4}', '\u{0}', '\u{0}']), ('\u{1c6}', ['\u{1c4}', '\u{0}', '\u{0}']),
+        ('\u{1c8}', ['\u{1c7}', '\u{0}', '\u{0}']), ('\u{1c9}', ['\u{1c7}', '\u{0}', '\u{0}']),
+        ('\u{1cb}', ['\u{1ca}', '\u{0}', '\u{0}']), ('\u{1cc}', ['\u{1ca}', '\u{0}', '\u{0}']),
+        ('\u{1ce}', ['\u{1cd}', '\u{0}', '\u{0}']), ('\u{1d0}', ['\u{1cf}', '\u{0}', '\u{0}']),
+        ('\u{1d2}', ['\u{1d1}', '\u{0}', '\u{0}']), ('\u{1d4}', ['\u{1d3}', '\u{0}', '\u{0}']),
+        ('\u{1d6}', ['\u{1d5}', '\u{0}', '\u{0}']), ('\u{1d8}', ['\u{1d7}', '\u{0}', '\u{0}']),
+        ('\u{1da}', ['\u{1d9}', '\u{0}', '\u{0}']), ('\u{1dc}', ['\u{1db}', '\u{0}', '\u{0}']),
+        ('\u{1dd}', ['\u{18e}', '\u{0}', '\u{0}']), ('\u{1df}', ['\u{1de}', '\u{0}', '\u{0}']),
+        ('\u{1e1}', ['\u{1e0}', '\u{0}', '\u{0}']), ('\u{1e3}', ['\u{1e2}', '\u{0}', '\u{0}']),
+        ('\u{1e5}', ['\u{1e4}', '\u{0}', '\u{0}']), ('\u{1e7}', ['\u{1e6}', '\u{0}', '\u{0}']),
+        ('\u{1e9}', ['\u{1e8}', '\u{0}', '\u{0}']), ('\u{1eb}', ['\u{1ea}', '\u{0}', '\u{0}']),
+        ('\u{1ed}', ['\u{1ec}', '\u{0}', '\u{0}']), ('\u{1ef}', ['\u{1ee}', '\u{0}', '\u{0}']),
+        ('\u{1f0}', ['J', '\u{30c}', '\u{0}']), ('\u{1f2}', ['\u{1f1}', '\u{0}', '\u{0}']),
+        ('\u{1f3}', ['\u{1f1}', '\u{0}', '\u{0}']), ('\u{1f5}', ['\u{1f4}', '\u{0}', '\u{0}']),
+        ('\u{1f9}', ['\u{1f8}', '\u{0}', '\u{0}']), ('\u{1fb}', ['\u{1fa}', '\u{0}', '\u{0}']),
+        ('\u{1fd}', ['\u{1fc}', '\u{0}', '\u{0}']), ('\u{1ff}', ['\u{1fe}', '\u{0}', '\u{0}']),
+        ('\u{201}', ['\u{200}', '\u{0}', '\u{0}']), ('\u{203}', ['\u{202}', '\u{0}', '\u{0}']),
+        ('\u{205}', ['\u{204}', '\u{0}', '\u{0}']), ('\u{207}', ['\u{206}', '\u{0}', '\u{0}']),
+        ('\u{209}', ['\u{208}', '\u{0}', '\u{0}']), ('\u{20b}', ['\u{20a}', '\u{0}', '\u{0}']),
+        ('\u{20d}', ['\u{20c}', '\u{0}', '\u{0}']), ('\u{20f}', ['\u{20e}', '\u{0}', '\u{0}']),
+        ('\u{211}', ['\u{210}', '\u{0}', '\u{0}']), ('\u{213}', ['\u{212}', '\u{0}', '\u{0}']),
+        ('\u{215}', ['\u{214}', '\u{0}', '\u{0}']), ('\u{217}', ['\u{216}', '\u{0}', '\u{0}']),
+        ('\u{219}', ['\u{218}', '\u{0}', '\u{0}']), ('\u{21b}', ['\u{21a}', '\u{0}', '\u{0}']),
+        ('\u{21d}', ['\u{21c}', '\u{0}', '\u{0}']), ('\u{21f}', ['\u{21e}', '\u{0}', '\u{0}']),
+        ('\u{223}', ['\u{222}', '\u{0}', '\u{0}']), ('\u{225}', ['\u{224}', '\u{0}', '\u{0}']),
+        ('\u{227}', ['\u{226}', '\u{0}', '\u{0}']), ('\u{229}', ['\u{228}', '\u{0}', '\u{0}']),
+        ('\u{22b}', ['\u{22a}', '\u{0}', '\u{0}']), ('\u{22d}', ['\u{22c}', '\u{0}', '\u{0}']),
+        ('\u{22f}', ['\u{22e}', '\u{0}', '\u{0}']), ('\u{231}', ['\u{230}', '\u{0}', '\u{0}']),
+        ('\u{233}', ['\u{232}', '\u{0}', '\u{0}']), ('\u{23c}', ['\u{23b}', '\u{0}', '\u{0}']),
+        ('\u{23f}', ['\u{2c7e}', '\u{0}', '\u{0}']), ('\u{240}', ['\u{2c7f}', '\u{0}', '\u{0}']),
+        ('\u{242}', ['\u{241}', '\u{0}', '\u{0}']), ('\u{247}', ['\u{246}', '\u{0}', '\u{0}']),
+        ('\u{249}', ['\u{248}', '\u{0}', '\u{0}']), ('\u{24b}', ['\u{24a}', '\u{0}', '\u{0}']),
+        ('\u{24d}', ['\u{24c}', '\u{0}', '\u{0}']), ('\u{24f}', ['\u{24e}', '\u{0}', '\u{0}']),
+        ('\u{250}', ['\u{2c6f}', '\u{0}', '\u{0}']), ('\u{251}', ['\u{2c6d}', '\u{0}', '\u{0}']),
+        ('\u{252}', ['\u{2c70}', '\u{0}', '\u{0}']), ('\u{253}', ['\u{181}', '\u{0}', '\u{0}']),
+        ('\u{254}', ['\u{186}', '\u{0}', '\u{0}']), ('\u{256}', ['\u{189}', '\u{0}', '\u{0}']),
+        ('\u{257}', ['\u{18a}', '\u{0}', '\u{0}']), ('\u{259}', ['\u{18f}', '\u{0}', '\u{0}']),
+        ('\u{25b}', ['\u{190}', '\u{0}', '\u{0}']), ('\u{25c}', ['\u{a7ab}', '\u{0}', '\u{0}']),
+        ('\u{260}', ['\u{193}', '\u{0}', '\u{0}']), ('\u{261}', ['\u{a7ac}', '\u{0}', '\u{0}']),
+        ('\u{263}', ['\u{194}', '\u{0}', '\u{0}']), ('\u{265}', ['\u{a78d}', '\u{0}', '\u{0}']),
+        ('\u{266}', ['\u{a7aa}', '\u{0}', '\u{0}']), ('\u{268}', ['\u{197}', '\u{0}', '\u{0}']),
+        ('\u{269}', ['\u{196}', '\u{0}', '\u{0}']), ('\u{26a}', ['\u{a7ae}', '\u{0}', '\u{0}']),
+        ('\u{26b}', ['\u{2c62}', '\u{0}', '\u{0}']), ('\u{26c}', ['\u{a7ad}', '\u{0}', '\u{0}']),
+        ('\u{26f}', ['\u{19c}', '\u{0}', '\u{0}']), ('\u{271}', ['\u{2c6e}', '\u{0}', '\u{0}']),
+        ('\u{272}', ['\u{19d}', '\u{0}', '\u{0}']), ('\u{275}', ['\u{19f}', '\u{0}', '\u{0}']),
+        ('\u{27d}', ['\u{2c64}', '\u{0}', '\u{0}']), ('\u{280}', ['\u{1a6}', '\u{0}', '\u{0}']),
+        ('\u{282}', ['\u{a7c5}', '\u{0}', '\u{0}']), ('\u{283}', ['\u{1a9}', '\u{0}', '\u{0}']),
+        ('\u{287}', ['\u{a7b1}', '\u{0}', '\u{0}']), ('\u{288}', ['\u{1ae}', '\u{0}', '\u{0}']),
+        ('\u{289}', ['\u{244}', '\u{0}', '\u{0}']), ('\u{28a}', ['\u{1b1}', '\u{0}', '\u{0}']),
+        ('\u{28b}', ['\u{1b2}', '\u{0}', '\u{0}']), ('\u{28c}', ['\u{245}', '\u{0}', '\u{0}']),
+        ('\u{292}', ['\u{1b7}', '\u{0}', '\u{0}']), ('\u{29d}', ['\u{a7b2}', '\u{0}', '\u{0}']),
+        ('\u{29e}', ['\u{a7b0}', '\u{0}', '\u{0}']), ('\u{345}', ['\u{399}', '\u{0}', '\u{0}']),
+        ('\u{371}', ['\u{370}', '\u{0}', '\u{0}']), ('\u{373}', ['\u{372}', '\u{0}', '\u{0}']),
+        ('\u{377}', ['\u{376}', '\u{0}', '\u{0}']), ('\u{37b}', ['\u{3fd}', '\u{0}', '\u{0}']),
+        ('\u{37c}', ['\u{3fe}', '\u{0}', '\u{0}']), ('\u{37d}', ['\u{3ff}', '\u{0}', '\u{0}']),
+        ('\u{390}', ['\u{399}', '\u{308}', '\u{301}']), ('\u{3ac}', ['\u{386}', '\u{0}', '\u{0}']),
+        ('\u{3ad}', ['\u{388}', '\u{0}', '\u{0}']), ('\u{3ae}', ['\u{389}', '\u{0}', '\u{0}']),
+        ('\u{3af}', ['\u{38a}', '\u{0}', '\u{0}']), ('\u{3b0}', ['\u{3a5}', '\u{308}', '\u{301}']),
+        ('\u{3b1}', ['\u{391}', '\u{0}', '\u{0}']), ('\u{3b2}', ['\u{392}', '\u{0}', '\u{0}']),
+        ('\u{3b3}', ['\u{393}', '\u{0}', '\u{0}']), ('\u{3b4}', ['\u{394}', '\u{0}', '\u{0}']),
+        ('\u{3b5}', ['\u{395}', '\u{0}', '\u{0}']), ('\u{3b6}', ['\u{396}', '\u{0}', '\u{0}']),
+        ('\u{3b7}', ['\u{397}', '\u{0}', '\u{0}']), ('\u{3b8}', ['\u{398}', '\u{0}', '\u{0}']),
+        ('\u{3b9}', ['\u{399}', '\u{0}', '\u{0}']), ('\u{3ba}', ['\u{39a}', '\u{0}', '\u{0}']),
+        ('\u{3bb}', ['\u{39b}', '\u{0}', '\u{0}']), ('\u{3bc}', ['\u{39c}', '\u{0}', '\u{0}']),
+        ('\u{3bd}', ['\u{39d}', '\u{0}', '\u{0}']), ('\u{3be}', ['\u{39e}', '\u{0}', '\u{0}']),
+        ('\u{3bf}', ['\u{39f}', '\u{0}', '\u{0}']), ('\u{3c0}', ['\u{3a0}', '\u{0}', '\u{0}']),
+        ('\u{3c1}', ['\u{3a1}', '\u{0}', '\u{0}']), ('\u{3c2}', ['\u{3a3}', '\u{0}', '\u{0}']),
+        ('\u{3c3}', ['\u{3a3}', '\u{0}', '\u{0}']), ('\u{3c4}', ['\u{3a4}', '\u{0}', '\u{0}']),
+        ('\u{3c5}', ['\u{3a5}', '\u{0}', '\u{0}']), ('\u{3c6}', ['\u{3a6}', '\u{0}', '\u{0}']),
+        ('\u{3c7}', ['\u{3a7}', '\u{0}', '\u{0}']), ('\u{3c8}', ['\u{3a8}', '\u{0}', '\u{0}']),
+        ('\u{3c9}', ['\u{3a9}', '\u{0}', '\u{0}']), ('\u{3ca}', ['\u{3aa}', '\u{0}', '\u{0}']),
+        ('\u{3cb}', ['\u{3ab}', '\u{0}', '\u{0}']), ('\u{3cc}', ['\u{38c}', '\u{0}', '\u{0}']),
+        ('\u{3cd}', ['\u{38e}', '\u{0}', '\u{0}']), ('\u{3ce}', ['\u{38f}', '\u{0}', '\u{0}']),
+        ('\u{3d0}', ['\u{392}', '\u{0}', '\u{0}']), ('\u{3d1}', ['\u{398}', '\u{0}', '\u{0}']),
+        ('\u{3d5}', ['\u{3a6}', '\u{0}', '\u{0}']), ('\u{3d6}', ['\u{3a0}', '\u{0}', '\u{0}']),
+        ('\u{3d7}', ['\u{3cf}', '\u{0}', '\u{0}']), ('\u{3d9}', ['\u{3d8}', '\u{0}', '\u{0}']),
+        ('\u{3db}', ['\u{3da}', '\u{0}', '\u{0}']), ('\u{3dd}', ['\u{3dc}', '\u{0}', '\u{0}']),
+        ('\u{3df}', ['\u{3de}', '\u{0}', '\u{0}']), ('\u{3e1}', ['\u{3e0}', '\u{0}', '\u{0}']),
+        ('\u{3e3}', ['\u{3e2}', '\u{0}', '\u{0}']), ('\u{3e5}', ['\u{3e4}', '\u{0}', '\u{0}']),
+        ('\u{3e7}', ['\u{3e6}', '\u{0}', '\u{0}']), ('\u{3e9}', ['\u{3e8}', '\u{0}', '\u{0}']),
+        ('\u{3eb}', ['\u{3ea}', '\u{0}', '\u{0}']), ('\u{3ed}', ['\u{3ec}', '\u{0}', '\u{0}']),
+        ('\u{3ef}', ['\u{3ee}', '\u{0}', '\u{0}']), ('\u{3f0}', ['\u{39a}', '\u{0}', '\u{0}']),
+        ('\u{3f1}', ['\u{3a1}', '\u{0}', '\u{0}']), ('\u{3f2}', ['\u{3f9}', '\u{0}', '\u{0}']),
+        ('\u{3f3}', ['\u{37f}', '\u{0}', '\u{0}']), ('\u{3f5}', ['\u{395}', '\u{0}', '\u{0}']),
+        ('\u{3f8}', ['\u{3f7}', '\u{0}', '\u{0}']), ('\u{3fb}', ['\u{3fa}', '\u{0}', '\u{0}']),
+        ('\u{430}', ['\u{410}', '\u{0}', '\u{0}']), ('\u{431}', ['\u{411}', '\u{0}', '\u{0}']),
+        ('\u{432}', ['\u{412}', '\u{0}', '\u{0}']), ('\u{433}', ['\u{413}', '\u{0}', '\u{0}']),
+        ('\u{434}', ['\u{414}', '\u{0}', '\u{0}']), ('\u{435}', ['\u{415}', '\u{0}', '\u{0}']),
+        ('\u{436}', ['\u{416}', '\u{0}', '\u{0}']), ('\u{437}', ['\u{417}', '\u{0}', '\u{0}']),
+        ('\u{438}', ['\u{418}', '\u{0}', '\u{0}']), ('\u{439}', ['\u{419}', '\u{0}', '\u{0}']),
+        ('\u{43a}', ['\u{41a}', '\u{0}', '\u{0}']), ('\u{43b}', ['\u{41b}', '\u{0}', '\u{0}']),
+        ('\u{43c}', ['\u{41c}', '\u{0}', '\u{0}']), ('\u{43d}', ['\u{41d}', '\u{0}', '\u{0}']),
+        ('\u{43e}', ['\u{41e}', '\u{0}', '\u{0}']), ('\u{43f}', ['\u{41f}', '\u{0}', '\u{0}']),
+        ('\u{440}', ['\u{420}', '\u{0}', '\u{0}']), ('\u{441}', ['\u{421}', '\u{0}', '\u{0}']),
+        ('\u{442}', ['\u{422}', '\u{0}', '\u{0}']), ('\u{443}', ['\u{423}', '\u{0}', '\u{0}']),
+        ('\u{444}', ['\u{424}', '\u{0}', '\u{0}']), ('\u{445}', ['\u{425}', '\u{0}', '\u{0}']),
+        ('\u{446}', ['\u{426}', '\u{0}', '\u{0}']), ('\u{447}', ['\u{427}', '\u{0}', '\u{0}']),
+        ('\u{448}', ['\u{428}', '\u{0}', '\u{0}']), ('\u{449}', ['\u{429}', '\u{0}', '\u{0}']),
+        ('\u{44a}', ['\u{42a}', '\u{0}', '\u{0}']), ('\u{44b}', ['\u{42b}', '\u{0}', '\u{0}']),
+        ('\u{44c}', ['\u{42c}', '\u{0}', '\u{0}']), ('\u{44d}', ['\u{42d}', '\u{0}', '\u{0}']),
+        ('\u{44e}', ['\u{42e}', '\u{0}', '\u{0}']), ('\u{44f}', ['\u{42f}', '\u{0}', '\u{0}']),
+        ('\u{450}', ['\u{400}', '\u{0}', '\u{0}']), ('\u{451}', ['\u{401}', '\u{0}', '\u{0}']),
+        ('\u{452}', ['\u{402}', '\u{0}', '\u{0}']), ('\u{453}', ['\u{403}', '\u{0}', '\u{0}']),
+        ('\u{454}', ['\u{404}', '\u{0}', '\u{0}']), ('\u{455}', ['\u{405}', '\u{0}', '\u{0}']),
+        ('\u{456}', ['\u{406}', '\u{0}', '\u{0}']), ('\u{457}', ['\u{407}', '\u{0}', '\u{0}']),
+        ('\u{458}', ['\u{408}', '\u{0}', '\u{0}']), ('\u{459}', ['\u{409}', '\u{0}', '\u{0}']),
+        ('\u{45a}', ['\u{40a}', '\u{0}', '\u{0}']), ('\u{45b}', ['\u{40b}', '\u{0}', '\u{0}']),
+        ('\u{45c}', ['\u{40c}', '\u{0}', '\u{0}']), ('\u{45d}', ['\u{40d}', '\u{0}', '\u{0}']),
+        ('\u{45e}', ['\u{40e}', '\u{0}', '\u{0}']), ('\u{45f}', ['\u{40f}', '\u{0}', '\u{0}']),
+        ('\u{461}', ['\u{460}', '\u{0}', '\u{0}']), ('\u{463}', ['\u{462}', '\u{0}', '\u{0}']),
+        ('\u{465}', ['\u{464}', '\u{0}', '\u{0}']), ('\u{467}', ['\u{466}', '\u{0}', '\u{0}']),
+        ('\u{469}', ['\u{468}', '\u{0}', '\u{0}']), ('\u{46b}', ['\u{46a}', '\u{0}', '\u{0}']),
+        ('\u{46d}', ['\u{46c}', '\u{0}', '\u{0}']), ('\u{46f}', ['\u{46e}', '\u{0}', '\u{0}']),
+        ('\u{471}', ['\u{470}', '\u{0}', '\u{0}']), ('\u{473}', ['\u{472}', '\u{0}', '\u{0}']),
+        ('\u{475}', ['\u{474}', '\u{0}', '\u{0}']), ('\u{477}', ['\u{476}', '\u{0}', '\u{0}']),
+        ('\u{479}', ['\u{478}', '\u{0}', '\u{0}']), ('\u{47b}', ['\u{47a}', '\u{0}', '\u{0}']),
+        ('\u{47d}', ['\u{47c}', '\u{0}', '\u{0}']), ('\u{47f}', ['\u{47e}', '\u{0}', '\u{0}']),
+        ('\u{481}', ['\u{480}', '\u{0}', '\u{0}']), ('\u{48b}', ['\u{48a}', '\u{0}', '\u{0}']),
+        ('\u{48d}', ['\u{48c}', '\u{0}', '\u{0}']), ('\u{48f}', ['\u{48e}', '\u{0}', '\u{0}']),
+        ('\u{491}', ['\u{490}', '\u{0}', '\u{0}']), ('\u{493}', ['\u{492}', '\u{0}', '\u{0}']),
+        ('\u{495}', ['\u{494}', '\u{0}', '\u{0}']), ('\u{497}', ['\u{496}', '\u{0}', '\u{0}']),
+        ('\u{499}', ['\u{498}', '\u{0}', '\u{0}']), ('\u{49b}', ['\u{49a}', '\u{0}', '\u{0}']),
+        ('\u{49d}', ['\u{49c}', '\u{0}', '\u{0}']), ('\u{49f}', ['\u{49e}', '\u{0}', '\u{0}']),
+        ('\u{4a1}', ['\u{4a0}', '\u{0}', '\u{0}']), ('\u{4a3}', ['\u{4a2}', '\u{0}', '\u{0}']),
+        ('\u{4a5}', ['\u{4a4}', '\u{0}', '\u{0}']), ('\u{4a7}', ['\u{4a6}', '\u{0}', '\u{0}']),
+        ('\u{4a9}', ['\u{4a8}', '\u{0}', '\u{0}']), ('\u{4ab}', ['\u{4aa}', '\u{0}', '\u{0}']),
+        ('\u{4ad}', ['\u{4ac}', '\u{0}', '\u{0}']), ('\u{4af}', ['\u{4ae}', '\u{0}', '\u{0}']),
+        ('\u{4b1}', ['\u{4b0}', '\u{0}', '\u{0}']), ('\u{4b3}', ['\u{4b2}', '\u{0}', '\u{0}']),
+        ('\u{4b5}', ['\u{4b4}', '\u{0}', '\u{0}']), ('\u{4b7}', ['\u{4b6}', '\u{0}', '\u{0}']),
+        ('\u{4b9}', ['\u{4b8}', '\u{0}', '\u{0}']), ('\u{4bb}', ['\u{4ba}', '\u{0}', '\u{0}']),
+        ('\u{4bd}', ['\u{4bc}', '\u{0}', '\u{0}']), ('\u{4bf}', ['\u{4be}', '\u{0}', '\u{0}']),
+        ('\u{4c2}', ['\u{4c1}', '\u{0}', '\u{0}']), ('\u{4c4}', ['\u{4c3}', '\u{0}', '\u{0}']),
+        ('\u{4c6}', ['\u{4c5}', '\u{0}', '\u{0}']), ('\u{4c8}', ['\u{4c7}', '\u{0}', '\u{0}']),
+        ('\u{4ca}', ['\u{4c9}', '\u{0}', '\u{0}']), ('\u{4cc}', ['\u{4cb}', '\u{0}', '\u{0}']),
+        ('\u{4ce}', ['\u{4cd}', '\u{0}', '\u{0}']), ('\u{4cf}', ['\u{4c0}', '\u{0}', '\u{0}']),
+        ('\u{4d1}', ['\u{4d0}', '\u{0}', '\u{0}']), ('\u{4d3}', ['\u{4d2}', '\u{0}', '\u{0}']),
+        ('\u{4d5}', ['\u{4d4}', '\u{0}', '\u{0}']), ('\u{4d7}', ['\u{4d6}', '\u{0}', '\u{0}']),
+        ('\u{4d9}', ['\u{4d8}', '\u{0}', '\u{0}']), ('\u{4db}', ['\u{4da}', '\u{0}', '\u{0}']),
+        ('\u{4dd}', ['\u{4dc}', '\u{0}', '\u{0}']), ('\u{4df}', ['\u{4de}', '\u{0}', '\u{0}']),
+        ('\u{4e1}', ['\u{4e0}', '\u{0}', '\u{0}']), ('\u{4e3}', ['\u{4e2}', '\u{0}', '\u{0}']),
+        ('\u{4e5}', ['\u{4e4}', '\u{0}', '\u{0}']), ('\u{4e7}', ['\u{4e6}', '\u{0}', '\u{0}']),
+        ('\u{4e9}', ['\u{4e8}', '\u{0}', '\u{0}']), ('\u{4eb}', ['\u{4ea}', '\u{0}', '\u{0}']),
+        ('\u{4ed}', ['\u{4ec}', '\u{0}', '\u{0}']), ('\u{4ef}', ['\u{4ee}', '\u{0}', '\u{0}']),
+        ('\u{4f1}', ['\u{4f0}', '\u{0}', '\u{0}']), ('\u{4f3}', ['\u{4f2}', '\u{0}', '\u{0}']),
+        ('\u{4f5}', ['\u{4f4}', '\u{0}', '\u{0}']), ('\u{4f7}', ['\u{4f6}', '\u{0}', '\u{0}']),
+        ('\u{4f9}', ['\u{4f8}', '\u{0}', '\u{0}']), ('\u{4fb}', ['\u{4fa}', '\u{0}', '\u{0}']),
+        ('\u{4fd}', ['\u{4fc}', '\u{0}', '\u{0}']), ('\u{4ff}', ['\u{4fe}', '\u{0}', '\u{0}']),
+        ('\u{501}', ['\u{500}', '\u{0}', '\u{0}']), ('\u{503}', ['\u{502}', '\u{0}', '\u{0}']),
+        ('\u{505}', ['\u{504}', '\u{0}', '\u{0}']), ('\u{507}', ['\u{506}', '\u{0}', '\u{0}']),
+        ('\u{509}', ['\u{508}', '\u{0}', '\u{0}']), ('\u{50b}', ['\u{50a}', '\u{0}', '\u{0}']),
+        ('\u{50d}', ['\u{50c}', '\u{0}', '\u{0}']), ('\u{50f}', ['\u{50e}', '\u{0}', '\u{0}']),
+        ('\u{511}', ['\u{510}', '\u{0}', '\u{0}']), ('\u{513}', ['\u{512}', '\u{0}', '\u{0}']),
+        ('\u{515}', ['\u{514}', '\u{0}', '\u{0}']), ('\u{517}', ['\u{516}', '\u{0}', '\u{0}']),
+        ('\u{519}', ['\u{518}', '\u{0}', '\u{0}']), ('\u{51b}', ['\u{51a}', '\u{0}', '\u{0}']),
+        ('\u{51d}', ['\u{51c}', '\u{0}', '\u{0}']), ('\u{51f}', ['\u{51e}', '\u{0}', '\u{0}']),
+        ('\u{521}', ['\u{520}', '\u{0}', '\u{0}']), ('\u{523}', ['\u{522}', '\u{0}', '\u{0}']),
+        ('\u{525}', ['\u{524}', '\u{0}', '\u{0}']), ('\u{527}', ['\u{526}', '\u{0}', '\u{0}']),
+        ('\u{529}', ['\u{528}', '\u{0}', '\u{0}']), ('\u{52b}', ['\u{52a}', '\u{0}', '\u{0}']),
+        ('\u{52d}', ['\u{52c}', '\u{0}', '\u{0}']), ('\u{52f}', ['\u{52e}', '\u{0}', '\u{0}']),
+        ('\u{561}', ['\u{531}', '\u{0}', '\u{0}']), ('\u{562}', ['\u{532}', '\u{0}', '\u{0}']),
+        ('\u{563}', ['\u{533}', '\u{0}', '\u{0}']), ('\u{564}', ['\u{534}', '\u{0}', '\u{0}']),
+        ('\u{565}', ['\u{535}', '\u{0}', '\u{0}']), ('\u{566}', ['\u{536}', '\u{0}', '\u{0}']),
+        ('\u{567}', ['\u{537}', '\u{0}', '\u{0}']), ('\u{568}', ['\u{538}', '\u{0}', '\u{0}']),
+        ('\u{569}', ['\u{539}', '\u{0}', '\u{0}']), ('\u{56a}', ['\u{53a}', '\u{0}', '\u{0}']),
+        ('\u{56b}', ['\u{53b}', '\u{0}', '\u{0}']), ('\u{56c}', ['\u{53c}', '\u{0}', '\u{0}']),
+        ('\u{56d}', ['\u{53d}', '\u{0}', '\u{0}']), ('\u{56e}', ['\u{53e}', '\u{0}', '\u{0}']),
+        ('\u{56f}', ['\u{53f}', '\u{0}', '\u{0}']), ('\u{570}', ['\u{540}', '\u{0}', '\u{0}']),
+        ('\u{571}', ['\u{541}', '\u{0}', '\u{0}']), ('\u{572}', ['\u{542}', '\u{0}', '\u{0}']),
+        ('\u{573}', ['\u{543}', '\u{0}', '\u{0}']), ('\u{574}', ['\u{544}', '\u{0}', '\u{0}']),
+        ('\u{575}', ['\u{545}', '\u{0}', '\u{0}']), ('\u{576}', ['\u{546}', '\u{0}', '\u{0}']),
+        ('\u{577}', ['\u{547}', '\u{0}', '\u{0}']), ('\u{578}', ['\u{548}', '\u{0}', '\u{0}']),
+        ('\u{579}', ['\u{549}', '\u{0}', '\u{0}']), ('\u{57a}', ['\u{54a}', '\u{0}', '\u{0}']),
+        ('\u{57b}', ['\u{54b}', '\u{0}', '\u{0}']), ('\u{57c}', ['\u{54c}', '\u{0}', '\u{0}']),
+        ('\u{57d}', ['\u{54d}', '\u{0}', '\u{0}']), ('\u{57e}', ['\u{54e}', '\u{0}', '\u{0}']),
+        ('\u{57f}', ['\u{54f}', '\u{0}', '\u{0}']), ('\u{580}', ['\u{550}', '\u{0}', '\u{0}']),
+        ('\u{581}', ['\u{551}', '\u{0}', '\u{0}']), ('\u{582}', ['\u{552}', '\u{0}', '\u{0}']),
+        ('\u{583}', ['\u{553}', '\u{0}', '\u{0}']), ('\u{584}', ['\u{554}', '\u{0}', '\u{0}']),
+        ('\u{585}', ['\u{555}', '\u{0}', '\u{0}']), ('\u{586}', ['\u{556}', '\u{0}', '\u{0}']),
+        ('\u{587}', ['\u{535}', '\u{552}', '\u{0}']), ('\u{10d0}', ['\u{1c90}', '\u{0}', '\u{0}']),
+        ('\u{10d1}', ['\u{1c91}', '\u{0}', '\u{0}']), ('\u{10d2}', ['\u{1c92}', '\u{0}', '\u{0}']),
+        ('\u{10d3}', ['\u{1c93}', '\u{0}', '\u{0}']), ('\u{10d4}', ['\u{1c94}', '\u{0}', '\u{0}']),
+        ('\u{10d5}', ['\u{1c95}', '\u{0}', '\u{0}']), ('\u{10d6}', ['\u{1c96}', '\u{0}', '\u{0}']),
+        ('\u{10d7}', ['\u{1c97}', '\u{0}', '\u{0}']), ('\u{10d8}', ['\u{1c98}', '\u{0}', '\u{0}']),
+        ('\u{10d9}', ['\u{1c99}', '\u{0}', '\u{0}']), ('\u{10da}', ['\u{1c9a}', '\u{0}', '\u{0}']),
+        ('\u{10db}', ['\u{1c9b}', '\u{0}', '\u{0}']), ('\u{10dc}', ['\u{1c9c}', '\u{0}', '\u{0}']),
+        ('\u{10dd}', ['\u{1c9d}', '\u{0}', '\u{0}']), ('\u{10de}', ['\u{1c9e}', '\u{0}', '\u{0}']),
+        ('\u{10df}', ['\u{1c9f}', '\u{0}', '\u{0}']), ('\u{10e0}', ['\u{1ca0}', '\u{0}', '\u{0}']),
+        ('\u{10e1}', ['\u{1ca1}', '\u{0}', '\u{0}']), ('\u{10e2}', ['\u{1ca2}', '\u{0}', '\u{0}']),
+        ('\u{10e3}', ['\u{1ca3}', '\u{0}', '\u{0}']), ('\u{10e4}', ['\u{1ca4}', '\u{0}', '\u{0}']),
+        ('\u{10e5}', ['\u{1ca5}', '\u{0}', '\u{0}']), ('\u{10e6}', ['\u{1ca6}', '\u{0}', '\u{0}']),
+        ('\u{10e7}', ['\u{1ca7}', '\u{0}', '\u{0}']), ('\u{10e8}', ['\u{1ca8}', '\u{0}', '\u{0}']),
+        ('\u{10e9}', ['\u{1ca9}', '\u{0}', '\u{0}']), ('\u{10ea}', ['\u{1caa}', '\u{0}', '\u{0}']),
+        ('\u{10eb}', ['\u{1cab}', '\u{0}', '\u{0}']), ('\u{10ec}', ['\u{1cac}', '\u{0}', '\u{0}']),
+        ('\u{10ed}', ['\u{1cad}', '\u{0}', '\u{0}']), ('\u{10ee}', ['\u{1cae}', '\u{0}', '\u{0}']),
+        ('\u{10ef}', ['\u{1caf}', '\u{0}', '\u{0}']), ('\u{10f0}', ['\u{1cb0}', '\u{0}', '\u{0}']),
+        ('\u{10f1}', ['\u{1cb1}', '\u{0}', '\u{0}']), ('\u{10f2}', ['\u{1cb2}', '\u{0}', '\u{0}']),
+        ('\u{10f3}', ['\u{1cb3}', '\u{0}', '\u{0}']), ('\u{10f4}', ['\u{1cb4}', '\u{0}', '\u{0}']),
+        ('\u{10f5}', ['\u{1cb5}', '\u{0}', '\u{0}']), ('\u{10f6}', ['\u{1cb6}', '\u{0}', '\u{0}']),
+        ('\u{10f7}', ['\u{1cb7}', '\u{0}', '\u{0}']), ('\u{10f8}', ['\u{1cb8}', '\u{0}', '\u{0}']),
+        ('\u{10f9}', ['\u{1cb9}', '\u{0}', '\u{0}']), ('\u{10fa}', ['\u{1cba}', '\u{0}', '\u{0}']),
+        ('\u{10fd}', ['\u{1cbd}', '\u{0}', '\u{0}']), ('\u{10fe}', ['\u{1cbe}', '\u{0}', '\u{0}']),
+        ('\u{10ff}', ['\u{1cbf}', '\u{0}', '\u{0}']), ('\u{13f8}', ['\u{13f0}', '\u{0}', '\u{0}']),
+        ('\u{13f9}', ['\u{13f1}', '\u{0}', '\u{0}']), ('\u{13fa}', ['\u{13f2}', '\u{0}', '\u{0}']),
+        ('\u{13fb}', ['\u{13f3}', '\u{0}', '\u{0}']), ('\u{13fc}', ['\u{13f4}', '\u{0}', '\u{0}']),
+        ('\u{13fd}', ['\u{13f5}', '\u{0}', '\u{0}']), ('\u{1c80}', ['\u{412}', '\u{0}', '\u{0}']),
+        ('\u{1c81}', ['\u{414}', '\u{0}', '\u{0}']), ('\u{1c82}', ['\u{41e}', '\u{0}', '\u{0}']),
+        ('\u{1c83}', ['\u{421}', '\u{0}', '\u{0}']), ('\u{1c84}', ['\u{422}', '\u{0}', '\u{0}']),
+        ('\u{1c85}', ['\u{422}', '\u{0}', '\u{0}']), ('\u{1c86}', ['\u{42a}', '\u{0}', '\u{0}']),
+        ('\u{1c87}', ['\u{462}', '\u{0}', '\u{0}']), ('\u{1c88}', ['\u{a64a}', '\u{0}', '\u{0}']),
+        ('\u{1d79}', ['\u{a77d}', '\u{0}', '\u{0}']), ('\u{1d7d}', ['\u{2c63}', '\u{0}', '\u{0}']),
+        ('\u{1d8e}', ['\u{a7c6}', '\u{0}', '\u{0}']), ('\u{1e01}', ['\u{1e00}', '\u{0}', '\u{0}']),
+        ('\u{1e03}', ['\u{1e02}', '\u{0}', '\u{0}']), ('\u{1e05}', ['\u{1e04}', '\u{0}', '\u{0}']),
+        ('\u{1e07}', ['\u{1e06}', '\u{0}', '\u{0}']), ('\u{1e09}', ['\u{1e08}', '\u{0}', '\u{0}']),
+        ('\u{1e0b}', ['\u{1e0a}', '\u{0}', '\u{0}']), ('\u{1e0d}', ['\u{1e0c}', '\u{0}', '\u{0}']),
+        ('\u{1e0f}', ['\u{1e0e}', '\u{0}', '\u{0}']), ('\u{1e11}', ['\u{1e10}', '\u{0}', '\u{0}']),
+        ('\u{1e13}', ['\u{1e12}', '\u{0}', '\u{0}']), ('\u{1e15}', ['\u{1e14}', '\u{0}', '\u{0}']),
+        ('\u{1e17}', ['\u{1e16}', '\u{0}', '\u{0}']), ('\u{1e19}', ['\u{1e18}', '\u{0}', '\u{0}']),
+        ('\u{1e1b}', ['\u{1e1a}', '\u{0}', '\u{0}']), ('\u{1e1d}', ['\u{1e1c}', '\u{0}', '\u{0}']),
+        ('\u{1e1f}', ['\u{1e1e}', '\u{0}', '\u{0}']), ('\u{1e21}', ['\u{1e20}', '\u{0}', '\u{0}']),
+        ('\u{1e23}', ['\u{1e22}', '\u{0}', '\u{0}']), ('\u{1e25}', ['\u{1e24}', '\u{0}', '\u{0}']),
+        ('\u{1e27}', ['\u{1e26}', '\u{0}', '\u{0}']), ('\u{1e29}', ['\u{1e28}', '\u{0}', '\u{0}']),
+        ('\u{1e2b}', ['\u{1e2a}', '\u{0}', '\u{0}']), ('\u{1e2d}', ['\u{1e2c}', '\u{0}', '\u{0}']),
+        ('\u{1e2f}', ['\u{1e2e}', '\u{0}', '\u{0}']), ('\u{1e31}', ['\u{1e30}', '\u{0}', '\u{0}']),
+        ('\u{1e33}', ['\u{1e32}', '\u{0}', '\u{0}']), ('\u{1e35}', ['\u{1e34}', '\u{0}', '\u{0}']),
+        ('\u{1e37}', ['\u{1e36}', '\u{0}', '\u{0}']), ('\u{1e39}', ['\u{1e38}', '\u{0}', '\u{0}']),
+        ('\u{1e3b}', ['\u{1e3a}', '\u{0}', '\u{0}']), ('\u{1e3d}', ['\u{1e3c}', '\u{0}', '\u{0}']),
+        ('\u{1e3f}', ['\u{1e3e}', '\u{0}', '\u{0}']), ('\u{1e41}', ['\u{1e40}', '\u{0}', '\u{0}']),
+        ('\u{1e43}', ['\u{1e42}', '\u{0}', '\u{0}']), ('\u{1e45}', ['\u{1e44}', '\u{0}', '\u{0}']),
+        ('\u{1e47}', ['\u{1e46}', '\u{0}', '\u{0}']), ('\u{1e49}', ['\u{1e48}', '\u{0}', '\u{0}']),
+        ('\u{1e4b}', ['\u{1e4a}', '\u{0}', '\u{0}']), ('\u{1e4d}', ['\u{1e4c}', '\u{0}', '\u{0}']),
+        ('\u{1e4f}', ['\u{1e4e}', '\u{0}', '\u{0}']), ('\u{1e51}', ['\u{1e50}', '\u{0}', '\u{0}']),
+        ('\u{1e53}', ['\u{1e52}', '\u{0}', '\u{0}']), ('\u{1e55}', ['\u{1e54}', '\u{0}', '\u{0}']),
+        ('\u{1e57}', ['\u{1e56}', '\u{0}', '\u{0}']), ('\u{1e59}', ['\u{1e58}', '\u{0}', '\u{0}']),
+        ('\u{1e5b}', ['\u{1e5a}', '\u{0}', '\u{0}']), ('\u{1e5d}', ['\u{1e5c}', '\u{0}', '\u{0}']),
+        ('\u{1e5f}', ['\u{1e5e}', '\u{0}', '\u{0}']), ('\u{1e61}', ['\u{1e60}', '\u{0}', '\u{0}']),
+        ('\u{1e63}', ['\u{1e62}', '\u{0}', '\u{0}']), ('\u{1e65}', ['\u{1e64}', '\u{0}', '\u{0}']),
+        ('\u{1e67}', ['\u{1e66}', '\u{0}', '\u{0}']), ('\u{1e69}', ['\u{1e68}', '\u{0}', '\u{0}']),
+        ('\u{1e6b}', ['\u{1e6a}', '\u{0}', '\u{0}']), ('\u{1e6d}', ['\u{1e6c}', '\u{0}', '\u{0}']),
+        ('\u{1e6f}', ['\u{1e6e}', '\u{0}', '\u{0}']), ('\u{1e71}', ['\u{1e70}', '\u{0}', '\u{0}']),
+        ('\u{1e73}', ['\u{1e72}', '\u{0}', '\u{0}']), ('\u{1e75}', ['\u{1e74}', '\u{0}', '\u{0}']),
+        ('\u{1e77}', ['\u{1e76}', '\u{0}', '\u{0}']), ('\u{1e79}', ['\u{1e78}', '\u{0}', '\u{0}']),
+        ('\u{1e7b}', ['\u{1e7a}', '\u{0}', '\u{0}']), ('\u{1e7d}', ['\u{1e7c}', '\u{0}', '\u{0}']),
+        ('\u{1e7f}', ['\u{1e7e}', '\u{0}', '\u{0}']), ('\u{1e81}', ['\u{1e80}', '\u{0}', '\u{0}']),
+        ('\u{1e83}', ['\u{1e82}', '\u{0}', '\u{0}']), ('\u{1e85}', ['\u{1e84}', '\u{0}', '\u{0}']),
+        ('\u{1e87}', ['\u{1e86}', '\u{0}', '\u{0}']), ('\u{1e89}', ['\u{1e88}', '\u{0}', '\u{0}']),
+        ('\u{1e8b}', ['\u{1e8a}', '\u{0}', '\u{0}']), ('\u{1e8d}', ['\u{1e8c}', '\u{0}', '\u{0}']),
+        ('\u{1e8f}', ['\u{1e8e}', '\u{0}', '\u{0}']), ('\u{1e91}', ['\u{1e90}', '\u{0}', '\u{0}']),
+        ('\u{1e93}', ['\u{1e92}', '\u{0}', '\u{0}']), ('\u{1e95}', ['\u{1e94}', '\u{0}', '\u{0}']),
+        ('\u{1e96}', ['H', '\u{331}', '\u{0}']), ('\u{1e97}', ['T', '\u{308}', '\u{0}']),
+        ('\u{1e98}', ['W', '\u{30a}', '\u{0}']), ('\u{1e99}', ['Y', '\u{30a}', '\u{0}']),
+        ('\u{1e9a}', ['A', '\u{2be}', '\u{0}']), ('\u{1e9b}', ['\u{1e60}', '\u{0}', '\u{0}']),
+        ('\u{1ea1}', ['\u{1ea0}', '\u{0}', '\u{0}']), ('\u{1ea3}', ['\u{1ea2}', '\u{0}', '\u{0}']),
+        ('\u{1ea5}', ['\u{1ea4}', '\u{0}', '\u{0}']), ('\u{1ea7}', ['\u{1ea6}', '\u{0}', '\u{0}']),
+        ('\u{1ea9}', ['\u{1ea8}', '\u{0}', '\u{0}']), ('\u{1eab}', ['\u{1eaa}', '\u{0}', '\u{0}']),
+        ('\u{1ead}', ['\u{1eac}', '\u{0}', '\u{0}']), ('\u{1eaf}', ['\u{1eae}', '\u{0}', '\u{0}']),
+        ('\u{1eb1}', ['\u{1eb0}', '\u{0}', '\u{0}']), ('\u{1eb3}', ['\u{1eb2}', '\u{0}', '\u{0}']),
+        ('\u{1eb5}', ['\u{1eb4}', '\u{0}', '\u{0}']), ('\u{1eb7}', ['\u{1eb6}', '\u{0}', '\u{0}']),
+        ('\u{1eb9}', ['\u{1eb8}', '\u{0}', '\u{0}']), ('\u{1ebb}', ['\u{1eba}', '\u{0}', '\u{0}']),
+        ('\u{1ebd}', ['\u{1ebc}', '\u{0}', '\u{0}']), ('\u{1ebf}', ['\u{1ebe}', '\u{0}', '\u{0}']),
+        ('\u{1ec1}', ['\u{1ec0}', '\u{0}', '\u{0}']), ('\u{1ec3}', ['\u{1ec2}', '\u{0}', '\u{0}']),
+        ('\u{1ec5}', ['\u{1ec4}', '\u{0}', '\u{0}']), ('\u{1ec7}', ['\u{1ec6}', '\u{0}', '\u{0}']),
+        ('\u{1ec9}', ['\u{1ec8}', '\u{0}', '\u{0}']), ('\u{1ecb}', ['\u{1eca}', '\u{0}', '\u{0}']),
+        ('\u{1ecd}', ['\u{1ecc}', '\u{0}', '\u{0}']), ('\u{1ecf}', ['\u{1ece}', '\u{0}', '\u{0}']),
+        ('\u{1ed1}', ['\u{1ed0}', '\u{0}', '\u{0}']), ('\u{1ed3}', ['\u{1ed2}', '\u{0}', '\u{0}']),
+        ('\u{1ed5}', ['\u{1ed4}', '\u{0}', '\u{0}']), ('\u{1ed7}', ['\u{1ed6}', '\u{0}', '\u{0}']),
+        ('\u{1ed9}', ['\u{1ed8}', '\u{0}', '\u{0}']), ('\u{1edb}', ['\u{1eda}', '\u{0}', '\u{0}']),
+        ('\u{1edd}', ['\u{1edc}', '\u{0}', '\u{0}']), ('\u{1edf}', ['\u{1ede}', '\u{0}', '\u{0}']),
+        ('\u{1ee1}', ['\u{1ee0}', '\u{0}', '\u{0}']), ('\u{1ee3}', ['\u{1ee2}', '\u{0}', '\u{0}']),
+        ('\u{1ee5}', ['\u{1ee4}', '\u{0}', '\u{0}']), ('\u{1ee7}', ['\u{1ee6}', '\u{0}', '\u{0}']),
+        ('\u{1ee9}', ['\u{1ee8}', '\u{0}', '\u{0}']), ('\u{1eeb}', ['\u{1eea}', '\u{0}', '\u{0}']),
+        ('\u{1eed}', ['\u{1eec}', '\u{0}', '\u{0}']), ('\u{1eef}', ['\u{1eee}', '\u{0}', '\u{0}']),
+        ('\u{1ef1}', ['\u{1ef0}', '\u{0}', '\u{0}']), ('\u{1ef3}', ['\u{1ef2}', '\u{0}', '\u{0}']),
+        ('\u{1ef5}', ['\u{1ef4}', '\u{0}', '\u{0}']), ('\u{1ef7}', ['\u{1ef6}', '\u{0}', '\u{0}']),
+        ('\u{1ef9}', ['\u{1ef8}', '\u{0}', '\u{0}']), ('\u{1efb}', ['\u{1efa}', '\u{0}', '\u{0}']),
+        ('\u{1efd}', ['\u{1efc}', '\u{0}', '\u{0}']), ('\u{1eff}', ['\u{1efe}', '\u{0}', '\u{0}']),
+        ('\u{1f00}', ['\u{1f08}', '\u{0}', '\u{0}']), ('\u{1f01}', ['\u{1f09}', '\u{0}', '\u{0}']),
+        ('\u{1f02}', ['\u{1f0a}', '\u{0}', '\u{0}']), ('\u{1f03}', ['\u{1f0b}', '\u{0}', '\u{0}']),
+        ('\u{1f04}', ['\u{1f0c}', '\u{0}', '\u{0}']), ('\u{1f05}', ['\u{1f0d}', '\u{0}', '\u{0}']),
+        ('\u{1f06}', ['\u{1f0e}', '\u{0}', '\u{0}']), ('\u{1f07}', ['\u{1f0f}', '\u{0}', '\u{0}']),
+        ('\u{1f10}', ['\u{1f18}', '\u{0}', '\u{0}']), ('\u{1f11}', ['\u{1f19}', '\u{0}', '\u{0}']),
+        ('\u{1f12}', ['\u{1f1a}', '\u{0}', '\u{0}']), ('\u{1f13}', ['\u{1f1b}', '\u{0}', '\u{0}']),
+        ('\u{1f14}', ['\u{1f1c}', '\u{0}', '\u{0}']), ('\u{1f15}', ['\u{1f1d}', '\u{0}', '\u{0}']),
+        ('\u{1f20}', ['\u{1f28}', '\u{0}', '\u{0}']), ('\u{1f21}', ['\u{1f29}', '\u{0}', '\u{0}']),
+        ('\u{1f22}', ['\u{1f2a}', '\u{0}', '\u{0}']), ('\u{1f23}', ['\u{1f2b}', '\u{0}', '\u{0}']),
+        ('\u{1f24}', ['\u{1f2c}', '\u{0}', '\u{0}']), ('\u{1f25}', ['\u{1f2d}', '\u{0}', '\u{0}']),
+        ('\u{1f26}', ['\u{1f2e}', '\u{0}', '\u{0}']), ('\u{1f27}', ['\u{1f2f}', '\u{0}', '\u{0}']),
+        ('\u{1f30}', ['\u{1f38}', '\u{0}', '\u{0}']), ('\u{1f31}', ['\u{1f39}', '\u{0}', '\u{0}']),
+        ('\u{1f32}', ['\u{1f3a}', '\u{0}', '\u{0}']), ('\u{1f33}', ['\u{1f3b}', '\u{0}', '\u{0}']),
+        ('\u{1f34}', ['\u{1f3c}', '\u{0}', '\u{0}']), ('\u{1f35}', ['\u{1f3d}', '\u{0}', '\u{0}']),
+        ('\u{1f36}', ['\u{1f3e}', '\u{0}', '\u{0}']), ('\u{1f37}', ['\u{1f3f}', '\u{0}', '\u{0}']),
+        ('\u{1f40}', ['\u{1f48}', '\u{0}', '\u{0}']), ('\u{1f41}', ['\u{1f49}', '\u{0}', '\u{0}']),
+        ('\u{1f42}', ['\u{1f4a}', '\u{0}', '\u{0}']), ('\u{1f43}', ['\u{1f4b}', '\u{0}', '\u{0}']),
+        ('\u{1f44}', ['\u{1f4c}', '\u{0}', '\u{0}']), ('\u{1f45}', ['\u{1f4d}', '\u{0}', '\u{0}']),
+        ('\u{1f50}', ['\u{3a5}', '\u{313}', '\u{0}']), ('\u{1f51}', ['\u{1f59}', '\u{0}', '\u{0}']),
+        ('\u{1f52}', ['\u{3a5}', '\u{313}', '\u{300}']),
+        ('\u{1f53}', ['\u{1f5b}', '\u{0}', '\u{0}']),
+        ('\u{1f54}', ['\u{3a5}', '\u{313}', '\u{301}']),
+        ('\u{1f55}', ['\u{1f5d}', '\u{0}', '\u{0}']),
+        ('\u{1f56}', ['\u{3a5}', '\u{313}', '\u{342}']),
+        ('\u{1f57}', ['\u{1f5f}', '\u{0}', '\u{0}']), ('\u{1f60}', ['\u{1f68}', '\u{0}', '\u{0}']),
+        ('\u{1f61}', ['\u{1f69}', '\u{0}', '\u{0}']), ('\u{1f62}', ['\u{1f6a}', '\u{0}', '\u{0}']),
+        ('\u{1f63}', ['\u{1f6b}', '\u{0}', '\u{0}']), ('\u{1f64}', ['\u{1f6c}', '\u{0}', '\u{0}']),
+        ('\u{1f65}', ['\u{1f6d}', '\u{0}', '\u{0}']), ('\u{1f66}', ['\u{1f6e}', '\u{0}', '\u{0}']),
+        ('\u{1f67}', ['\u{1f6f}', '\u{0}', '\u{0}']), ('\u{1f70}', ['\u{1fba}', '\u{0}', '\u{0}']),
+        ('\u{1f71}', ['\u{1fbb}', '\u{0}', '\u{0}']), ('\u{1f72}', ['\u{1fc8}', '\u{0}', '\u{0}']),
+        ('\u{1f73}', ['\u{1fc9}', '\u{0}', '\u{0}']), ('\u{1f74}', ['\u{1fca}', '\u{0}', '\u{0}']),
+        ('\u{1f75}', ['\u{1fcb}', '\u{0}', '\u{0}']), ('\u{1f76}', ['\u{1fda}', '\u{0}', '\u{0}']),
+        ('\u{1f77}', ['\u{1fdb}', '\u{0}', '\u{0}']), ('\u{1f78}', ['\u{1ff8}', '\u{0}', '\u{0}']),
+        ('\u{1f79}', ['\u{1ff9}', '\u{0}', '\u{0}']), ('\u{1f7a}', ['\u{1fea}', '\u{0}', '\u{0}']),
+        ('\u{1f7b}', ['\u{1feb}', '\u{0}', '\u{0}']), ('\u{1f7c}', ['\u{1ffa}', '\u{0}', '\u{0}']),
+        ('\u{1f7d}', ['\u{1ffb}', '\u{0}', '\u{0}']),
+        ('\u{1f80}', ['\u{1f08}', '\u{399}', '\u{0}']),
+        ('\u{1f81}', ['\u{1f09}', '\u{399}', '\u{0}']),
+        ('\u{1f82}', ['\u{1f0a}', '\u{399}', '\u{0}']),
+        ('\u{1f83}', ['\u{1f0b}', '\u{399}', '\u{0}']),
+        ('\u{1f84}', ['\u{1f0c}', '\u{399}', '\u{0}']),
+        ('\u{1f85}', ['\u{1f0d}', '\u{399}', '\u{0}']),
+        ('\u{1f86}', ['\u{1f0e}', '\u{399}', '\u{0}']),
+        ('\u{1f87}', ['\u{1f0f}', '\u{399}', '\u{0}']),
+        ('\u{1f88}', ['\u{1f08}', '\u{399}', '\u{0}']),
+        ('\u{1f89}', ['\u{1f09}', '\u{399}', '\u{0}']),
+        ('\u{1f8a}', ['\u{1f0a}', '\u{399}', '\u{0}']),
+        ('\u{1f8b}', ['\u{1f0b}', '\u{399}', '\u{0}']),
+        ('\u{1f8c}', ['\u{1f0c}', '\u{399}', '\u{0}']),
+        ('\u{1f8d}', ['\u{1f0d}', '\u{399}', '\u{0}']),
+        ('\u{1f8e}', ['\u{1f0e}', '\u{399}', '\u{0}']),
+        ('\u{1f8f}', ['\u{1f0f}', '\u{399}', '\u{0}']),
+        ('\u{1f90}', ['\u{1f28}', '\u{399}', '\u{0}']),
+        ('\u{1f91}', ['\u{1f29}', '\u{399}', '\u{0}']),
+        ('\u{1f92}', ['\u{1f2a}', '\u{399}', '\u{0}']),
+        ('\u{1f93}', ['\u{1f2b}', '\u{399}', '\u{0}']),
+        ('\u{1f94}', ['\u{1f2c}', '\u{399}', '\u{0}']),
+        ('\u{1f95}', ['\u{1f2d}', '\u{399}', '\u{0}']),
+        ('\u{1f96}', ['\u{1f2e}', '\u{399}', '\u{0}']),
+        ('\u{1f97}', ['\u{1f2f}', '\u{399}', '\u{0}']),
+        ('\u{1f98}', ['\u{1f28}', '\u{399}', '\u{0}']),
+        ('\u{1f99}', ['\u{1f29}', '\u{399}', '\u{0}']),
+        ('\u{1f9a}', ['\u{1f2a}', '\u{399}', '\u{0}']),
+        ('\u{1f9b}', ['\u{1f2b}', '\u{399}', '\u{0}']),
+        ('\u{1f9c}', ['\u{1f2c}', '\u{399}', '\u{0}']),
+        ('\u{1f9d}', ['\u{1f2d}', '\u{399}', '\u{0}']),
+        ('\u{1f9e}', ['\u{1f2e}', '\u{399}', '\u{0}']),
+        ('\u{1f9f}', ['\u{1f2f}', '\u{399}', '\u{0}']),
+        ('\u{1fa0}', ['\u{1f68}', '\u{399}', '\u{0}']),
+        ('\u{1fa1}', ['\u{1f69}', '\u{399}', '\u{0}']),
+        ('\u{1fa2}', ['\u{1f6a}', '\u{399}', '\u{0}']),
+        ('\u{1fa3}', ['\u{1f6b}', '\u{399}', '\u{0}']),
+        ('\u{1fa4}', ['\u{1f6c}', '\u{399}', '\u{0}']),
+        ('\u{1fa5}', ['\u{1f6d}', '\u{399}', '\u{0}']),
+        ('\u{1fa6}', ['\u{1f6e}', '\u{399}', '\u{0}']),
+        ('\u{1fa7}', ['\u{1f6f}', '\u{399}', '\u{0}']),
+        ('\u{1fa8}', ['\u{1f68}', '\u{399}', '\u{0}']),
+        ('\u{1fa9}', ['\u{1f69}', '\u{399}', '\u{0}']),
+        ('\u{1faa}', ['\u{1f6a}', '\u{399}', '\u{0}']),
+        ('\u{1fab}', ['\u{1f6b}', '\u{399}', '\u{0}']),
+        ('\u{1fac}', ['\u{1f6c}', '\u{399}', '\u{0}']),
+        ('\u{1fad}', ['\u{1f6d}', '\u{399}', '\u{0}']),
+        ('\u{1fae}', ['\u{1f6e}', '\u{399}', '\u{0}']),
+        ('\u{1faf}', ['\u{1f6f}', '\u{399}', '\u{0}']),
+        ('\u{1fb0}', ['\u{1fb8}', '\u{0}', '\u{0}']), ('\u{1fb1}', ['\u{1fb9}', '\u{0}', '\u{0}']),
+        ('\u{1fb2}', ['\u{1fba}', '\u{399}', '\u{0}']),
+        ('\u{1fb3}', ['\u{391}', '\u{399}', '\u{0}']),
+        ('\u{1fb4}', ['\u{386}', '\u{399}', '\u{0}']),
+        ('\u{1fb6}', ['\u{391}', '\u{342}', '\u{0}']),
+        ('\u{1fb7}', ['\u{391}', '\u{342}', '\u{399}']),
+        ('\u{1fbc}', ['\u{391}', '\u{399}', '\u{0}']), ('\u{1fbe}', ['\u{399}', '\u{0}', '\u{0}']),
+        ('\u{1fc2}', ['\u{1fca}', '\u{399}', '\u{0}']),
+        ('\u{1fc3}', ['\u{397}', '\u{399}', '\u{0}']),
+        ('\u{1fc4}', ['\u{389}', '\u{399}', '\u{0}']),
+        ('\u{1fc6}', ['\u{397}', '\u{342}', '\u{0}']),
+        ('\u{1fc7}', ['\u{397}', '\u{342}', '\u{399}']),
+        ('\u{1fcc}', ['\u{397}', '\u{399}', '\u{0}']), ('\u{1fd0}', ['\u{1fd8}', '\u{0}', '\u{0}']),
+        ('\u{1fd1}', ['\u{1fd9}', '\u{0}', '\u{0}']),
+        ('\u{1fd2}', ['\u{399}', '\u{308}', '\u{300}']),
+        ('\u{1fd3}', ['\u{399}', '\u{308}', '\u{301}']),
+        ('\u{1fd6}', ['\u{399}', '\u{342}', '\u{0}']),
+        ('\u{1fd7}', ['\u{399}', '\u{308}', '\u{342}']),
+        ('\u{1fe0}', ['\u{1fe8}', '\u{0}', '\u{0}']), ('\u{1fe1}', ['\u{1fe9}', '\u{0}', '\u{0}']),
+        ('\u{1fe2}', ['\u{3a5}', '\u{308}', '\u{300}']),
+        ('\u{1fe3}', ['\u{3a5}', '\u{308}', '\u{301}']),
+        ('\u{1fe4}', ['\u{3a1}', '\u{313}', '\u{0}']), ('\u{1fe5}', ['\u{1fec}', '\u{0}', '\u{0}']),
+        ('\u{1fe6}', ['\u{3a5}', '\u{342}', '\u{0}']),
+        ('\u{1fe7}', ['\u{3a5}', '\u{308}', '\u{342}']),
+        ('\u{1ff2}', ['\u{1ffa}', '\u{399}', '\u{0}']),
+        ('\u{1ff3}', ['\u{3a9}', '\u{399}', '\u{0}']),
+        ('\u{1ff4}', ['\u{38f}', '\u{399}', '\u{0}']),
+        ('\u{1ff6}', ['\u{3a9}', '\u{342}', '\u{0}']),
+        ('\u{1ff7}', ['\u{3a9}', '\u{342}', '\u{399}']),
+        ('\u{1ffc}', ['\u{3a9}', '\u{399}', '\u{0}']), ('\u{214e}', ['\u{2132}', '\u{0}', '\u{0}']),
+        ('\u{2170}', ['\u{2160}', '\u{0}', '\u{0}']), ('\u{2171}', ['\u{2161}', '\u{0}', '\u{0}']),
+        ('\u{2172}', ['\u{2162}', '\u{0}', '\u{0}']), ('\u{2173}', ['\u{2163}', '\u{0}', '\u{0}']),
+        ('\u{2174}', ['\u{2164}', '\u{0}', '\u{0}']), ('\u{2175}', ['\u{2165}', '\u{0}', '\u{0}']),
+        ('\u{2176}', ['\u{2166}', '\u{0}', '\u{0}']), ('\u{2177}', ['\u{2167}', '\u{0}', '\u{0}']),
+        ('\u{2178}', ['\u{2168}', '\u{0}', '\u{0}']), ('\u{2179}', ['\u{2169}', '\u{0}', '\u{0}']),
+        ('\u{217a}', ['\u{216a}', '\u{0}', '\u{0}']), ('\u{217b}', ['\u{216b}', '\u{0}', '\u{0}']),
+        ('\u{217c}', ['\u{216c}', '\u{0}', '\u{0}']), ('\u{217d}', ['\u{216d}', '\u{0}', '\u{0}']),
+        ('\u{217e}', ['\u{216e}', '\u{0}', '\u{0}']), ('\u{217f}', ['\u{216f}', '\u{0}', '\u{0}']),
+        ('\u{2184}', ['\u{2183}', '\u{0}', '\u{0}']), ('\u{24d0}', ['\u{24b6}', '\u{0}', '\u{0}']),
+        ('\u{24d1}', ['\u{24b7}', '\u{0}', '\u{0}']), ('\u{24d2}', ['\u{24b8}', '\u{0}', '\u{0}']),
+        ('\u{24d3}', ['\u{24b9}', '\u{0}', '\u{0}']), ('\u{24d4}', ['\u{24ba}', '\u{0}', '\u{0}']),
+        ('\u{24d5}', ['\u{24bb}', '\u{0}', '\u{0}']), ('\u{24d6}', ['\u{24bc}', '\u{0}', '\u{0}']),
+        ('\u{24d7}', ['\u{24bd}', '\u{0}', '\u{0}']), ('\u{24d8}', ['\u{24be}', '\u{0}', '\u{0}']),
+        ('\u{24d9}', ['\u{24bf}', '\u{0}', '\u{0}']), ('\u{24da}', ['\u{24c0}', '\u{0}', '\u{0}']),
+        ('\u{24db}', ['\u{24c1}', '\u{0}', '\u{0}']), ('\u{24dc}', ['\u{24c2}', '\u{0}', '\u{0}']),
+        ('\u{24dd}', ['\u{24c3}', '\u{0}', '\u{0}']), ('\u{24de}', ['\u{24c4}', '\u{0}', '\u{0}']),
+        ('\u{24df}', ['\u{24c5}', '\u{0}', '\u{0}']), ('\u{24e0}', ['\u{24c6}', '\u{0}', '\u{0}']),
+        ('\u{24e1}', ['\u{24c7}', '\u{0}', '\u{0}']), ('\u{24e2}', ['\u{24c8}', '\u{0}', '\u{0}']),
+        ('\u{24e3}', ['\u{24c9}', '\u{0}', '\u{0}']), ('\u{24e4}', ['\u{24ca}', '\u{0}', '\u{0}']),
+        ('\u{24e5}', ['\u{24cb}', '\u{0}', '\u{0}']), ('\u{24e6}', ['\u{24cc}', '\u{0}', '\u{0}']),
+        ('\u{24e7}', ['\u{24cd}', '\u{0}', '\u{0}']), ('\u{24e8}', ['\u{24ce}', '\u{0}', '\u{0}']),
+        ('\u{24e9}', ['\u{24cf}', '\u{0}', '\u{0}']), ('\u{2c30}', ['\u{2c00}', '\u{0}', '\u{0}']),
+        ('\u{2c31}', ['\u{2c01}', '\u{0}', '\u{0}']), ('\u{2c32}', ['\u{2c02}', '\u{0}', '\u{0}']),
+        ('\u{2c33}', ['\u{2c03}', '\u{0}', '\u{0}']), ('\u{2c34}', ['\u{2c04}', '\u{0}', '\u{0}']),
+        ('\u{2c35}', ['\u{2c05}', '\u{0}', '\u{0}']), ('\u{2c36}', ['\u{2c06}', '\u{0}', '\u{0}']),
+        ('\u{2c37}', ['\u{2c07}', '\u{0}', '\u{0}']), ('\u{2c38}', ['\u{2c08}', '\u{0}', '\u{0}']),
+        ('\u{2c39}', ['\u{2c09}', '\u{0}', '\u{0}']), ('\u{2c3a}', ['\u{2c0a}', '\u{0}', '\u{0}']),
+        ('\u{2c3b}', ['\u{2c0b}', '\u{0}', '\u{0}']), ('\u{2c3c}', ['\u{2c0c}', '\u{0}', '\u{0}']),
+        ('\u{2c3d}', ['\u{2c0d}', '\u{0}', '\u{0}']), ('\u{2c3e}', ['\u{2c0e}', '\u{0}', '\u{0}']),
+        ('\u{2c3f}', ['\u{2c0f}', '\u{0}', '\u{0}']), ('\u{2c40}', ['\u{2c10}', '\u{0}', '\u{0}']),
+        ('\u{2c41}', ['\u{2c11}', '\u{0}', '\u{0}']), ('\u{2c42}', ['\u{2c12}', '\u{0}', '\u{0}']),
+        ('\u{2c43}', ['\u{2c13}', '\u{0}', '\u{0}']), ('\u{2c44}', ['\u{2c14}', '\u{0}', '\u{0}']),
+        ('\u{2c45}', ['\u{2c15}', '\u{0}', '\u{0}']), ('\u{2c46}', ['\u{2c16}', '\u{0}', '\u{0}']),
+        ('\u{2c47}', ['\u{2c17}', '\u{0}', '\u{0}']), ('\u{2c48}', ['\u{2c18}', '\u{0}', '\u{0}']),
+        ('\u{2c49}', ['\u{2c19}', '\u{0}', '\u{0}']), ('\u{2c4a}', ['\u{2c1a}', '\u{0}', '\u{0}']),
+        ('\u{2c4b}', ['\u{2c1b}', '\u{0}', '\u{0}']), ('\u{2c4c}', ['\u{2c1c}', '\u{0}', '\u{0}']),
+        ('\u{2c4d}', ['\u{2c1d}', '\u{0}', '\u{0}']), ('\u{2c4e}', ['\u{2c1e}', '\u{0}', '\u{0}']),
+        ('\u{2c4f}', ['\u{2c1f}', '\u{0}', '\u{0}']), ('\u{2c50}', ['\u{2c20}', '\u{0}', '\u{0}']),
+        ('\u{2c51}', ['\u{2c21}', '\u{0}', '\u{0}']), ('\u{2c52}', ['\u{2c22}', '\u{0}', '\u{0}']),
+        ('\u{2c53}', ['\u{2c23}', '\u{0}', '\u{0}']), ('\u{2c54}', ['\u{2c24}', '\u{0}', '\u{0}']),
+        ('\u{2c55}', ['\u{2c25}', '\u{0}', '\u{0}']), ('\u{2c56}', ['\u{2c26}', '\u{0}', '\u{0}']),
+        ('\u{2c57}', ['\u{2c27}', '\u{0}', '\u{0}']), ('\u{2c58}', ['\u{2c28}', '\u{0}', '\u{0}']),
+        ('\u{2c59}', ['\u{2c29}', '\u{0}', '\u{0}']), ('\u{2c5a}', ['\u{2c2a}', '\u{0}', '\u{0}']),
+        ('\u{2c5b}', ['\u{2c2b}', '\u{0}', '\u{0}']), ('\u{2c5c}', ['\u{2c2c}', '\u{0}', '\u{0}']),
+        ('\u{2c5d}', ['\u{2c2d}', '\u{0}', '\u{0}']), ('\u{2c5e}', ['\u{2c2e}', '\u{0}', '\u{0}']),
+        ('\u{2c61}', ['\u{2c60}', '\u{0}', '\u{0}']), ('\u{2c65}', ['\u{23a}', '\u{0}', '\u{0}']),
+        ('\u{2c66}', ['\u{23e}', '\u{0}', '\u{0}']), ('\u{2c68}', ['\u{2c67}', '\u{0}', '\u{0}']),
+        ('\u{2c6a}', ['\u{2c69}', '\u{0}', '\u{0}']), ('\u{2c6c}', ['\u{2c6b}', '\u{0}', '\u{0}']),
+        ('\u{2c73}', ['\u{2c72}', '\u{0}', '\u{0}']), ('\u{2c76}', ['\u{2c75}', '\u{0}', '\u{0}']),
+        ('\u{2c81}', ['\u{2c80}', '\u{0}', '\u{0}']), ('\u{2c83}', ['\u{2c82}', '\u{0}', '\u{0}']),
+        ('\u{2c85}', ['\u{2c84}', '\u{0}', '\u{0}']), ('\u{2c87}', ['\u{2c86}', '\u{0}', '\u{0}']),
+        ('\u{2c89}', ['\u{2c88}', '\u{0}', '\u{0}']), ('\u{2c8b}', ['\u{2c8a}', '\u{0}', '\u{0}']),
+        ('\u{2c8d}', ['\u{2c8c}', '\u{0}', '\u{0}']), ('\u{2c8f}', ['\u{2c8e}', '\u{0}', '\u{0}']),
+        ('\u{2c91}', ['\u{2c90}', '\u{0}', '\u{0}']), ('\u{2c93}', ['\u{2c92}', '\u{0}', '\u{0}']),
+        ('\u{2c95}', ['\u{2c94}', '\u{0}', '\u{0}']), ('\u{2c97}', ['\u{2c96}', '\u{0}', '\u{0}']),
+        ('\u{2c99}', ['\u{2c98}', '\u{0}', '\u{0}']), ('\u{2c9b}', ['\u{2c9a}', '\u{0}', '\u{0}']),
+        ('\u{2c9d}', ['\u{2c9c}', '\u{0}', '\u{0}']), ('\u{2c9f}', ['\u{2c9e}', '\u{0}', '\u{0}']),
+        ('\u{2ca1}', ['\u{2ca0}', '\u{0}', '\u{0}']), ('\u{2ca3}', ['\u{2ca2}', '\u{0}', '\u{0}']),
+        ('\u{2ca5}', ['\u{2ca4}', '\u{0}', '\u{0}']), ('\u{2ca7}', ['\u{2ca6}', '\u{0}', '\u{0}']),
+        ('\u{2ca9}', ['\u{2ca8}', '\u{0}', '\u{0}']), ('\u{2cab}', ['\u{2caa}', '\u{0}', '\u{0}']),
+        ('\u{2cad}', ['\u{2cac}', '\u{0}', '\u{0}']), ('\u{2caf}', ['\u{2cae}', '\u{0}', '\u{0}']),
+        ('\u{2cb1}', ['\u{2cb0}', '\u{0}', '\u{0}']), ('\u{2cb3}', ['\u{2cb2}', '\u{0}', '\u{0}']),
+        ('\u{2cb5}', ['\u{2cb4}', '\u{0}', '\u{0}']), ('\u{2cb7}', ['\u{2cb6}', '\u{0}', '\u{0}']),
+        ('\u{2cb9}', ['\u{2cb8}', '\u{0}', '\u{0}']), ('\u{2cbb}', ['\u{2cba}', '\u{0}', '\u{0}']),
+        ('\u{2cbd}', ['\u{2cbc}', '\u{0}', '\u{0}']), ('\u{2cbf}', ['\u{2cbe}', '\u{0}', '\u{0}']),
+        ('\u{2cc1}', ['\u{2cc0}', '\u{0}', '\u{0}']), ('\u{2cc3}', ['\u{2cc2}', '\u{0}', '\u{0}']),
+        ('\u{2cc5}', ['\u{2cc4}', '\u{0}', '\u{0}']), ('\u{2cc7}', ['\u{2cc6}', '\u{0}', '\u{0}']),
+        ('\u{2cc9}', ['\u{2cc8}', '\u{0}', '\u{0}']), ('\u{2ccb}', ['\u{2cca}', '\u{0}', '\u{0}']),
+        ('\u{2ccd}', ['\u{2ccc}', '\u{0}', '\u{0}']), ('\u{2ccf}', ['\u{2cce}', '\u{0}', '\u{0}']),
+        ('\u{2cd1}', ['\u{2cd0}', '\u{0}', '\u{0}']), ('\u{2cd3}', ['\u{2cd2}', '\u{0}', '\u{0}']),
+        ('\u{2cd5}', ['\u{2cd4}', '\u{0}', '\u{0}']), ('\u{2cd7}', ['\u{2cd6}', '\u{0}', '\u{0}']),
+        ('\u{2cd9}', ['\u{2cd8}', '\u{0}', '\u{0}']), ('\u{2cdb}', ['\u{2cda}', '\u{0}', '\u{0}']),
+        ('\u{2cdd}', ['\u{2cdc}', '\u{0}', '\u{0}']), ('\u{2cdf}', ['\u{2cde}', '\u{0}', '\u{0}']),
+        ('\u{2ce1}', ['\u{2ce0}', '\u{0}', '\u{0}']), ('\u{2ce3}', ['\u{2ce2}', '\u{0}', '\u{0}']),
+        ('\u{2cec}', ['\u{2ceb}', '\u{0}', '\u{0}']), ('\u{2cee}', ['\u{2ced}', '\u{0}', '\u{0}']),
+        ('\u{2cf3}', ['\u{2cf2}', '\u{0}', '\u{0}']), ('\u{2d00}', ['\u{10a0}', '\u{0}', '\u{0}']),
+        ('\u{2d01}', ['\u{10a1}', '\u{0}', '\u{0}']), ('\u{2d02}', ['\u{10a2}', '\u{0}', '\u{0}']),
+        ('\u{2d03}', ['\u{10a3}', '\u{0}', '\u{0}']), ('\u{2d04}', ['\u{10a4}', '\u{0}', '\u{0}']),
+        ('\u{2d05}', ['\u{10a5}', '\u{0}', '\u{0}']), ('\u{2d06}', ['\u{10a6}', '\u{0}', '\u{0}']),
+        ('\u{2d07}', ['\u{10a7}', '\u{0}', '\u{0}']), ('\u{2d08}', ['\u{10a8}', '\u{0}', '\u{0}']),
+        ('\u{2d09}', ['\u{10a9}', '\u{0}', '\u{0}']), ('\u{2d0a}', ['\u{10aa}', '\u{0}', '\u{0}']),
+        ('\u{2d0b}', ['\u{10ab}', '\u{0}', '\u{0}']), ('\u{2d0c}', ['\u{10ac}', '\u{0}', '\u{0}']),
+        ('\u{2d0d}', ['\u{10ad}', '\u{0}', '\u{0}']), ('\u{2d0e}', ['\u{10ae}', '\u{0}', '\u{0}']),
+        ('\u{2d0f}', ['\u{10af}', '\u{0}', '\u{0}']), ('\u{2d10}', ['\u{10b0}', '\u{0}', '\u{0}']),
+        ('\u{2d11}', ['\u{10b1}', '\u{0}', '\u{0}']), ('\u{2d12}', ['\u{10b2}', '\u{0}', '\u{0}']),
+        ('\u{2d13}', ['\u{10b3}', '\u{0}', '\u{0}']), ('\u{2d14}', ['\u{10b4}', '\u{0}', '\u{0}']),
+        ('\u{2d15}', ['\u{10b5}', '\u{0}', '\u{0}']), ('\u{2d16}', ['\u{10b6}', '\u{0}', '\u{0}']),
+        ('\u{2d17}', ['\u{10b7}', '\u{0}', '\u{0}']), ('\u{2d18}', ['\u{10b8}', '\u{0}', '\u{0}']),
+        ('\u{2d19}', ['\u{10b9}', '\u{0}', '\u{0}']), ('\u{2d1a}', ['\u{10ba}', '\u{0}', '\u{0}']),
+        ('\u{2d1b}', ['\u{10bb}', '\u{0}', '\u{0}']), ('\u{2d1c}', ['\u{10bc}', '\u{0}', '\u{0}']),
+        ('\u{2d1d}', ['\u{10bd}', '\u{0}', '\u{0}']), ('\u{2d1e}', ['\u{10be}', '\u{0}', '\u{0}']),
+        ('\u{2d1f}', ['\u{10bf}', '\u{0}', '\u{0}']), ('\u{2d20}', ['\u{10c0}', '\u{0}', '\u{0}']),
+        ('\u{2d21}', ['\u{10c1}', '\u{0}', '\u{0}']), ('\u{2d22}', ['\u{10c2}', '\u{0}', '\u{0}']),
+        ('\u{2d23}', ['\u{10c3}', '\u{0}', '\u{0}']), ('\u{2d24}', ['\u{10c4}', '\u{0}', '\u{0}']),
+        ('\u{2d25}', ['\u{10c5}', '\u{0}', '\u{0}']), ('\u{2d27}', ['\u{10c7}', '\u{0}', '\u{0}']),
+        ('\u{2d2d}', ['\u{10cd}', '\u{0}', '\u{0}']), ('\u{a641}', ['\u{a640}', '\u{0}', '\u{0}']),
+        ('\u{a643}', ['\u{a642}', '\u{0}', '\u{0}']), ('\u{a645}', ['\u{a644}', '\u{0}', '\u{0}']),
+        ('\u{a647}', ['\u{a646}', '\u{0}', '\u{0}']), ('\u{a649}', ['\u{a648}', '\u{0}', '\u{0}']),
+        ('\u{a64b}', ['\u{a64a}', '\u{0}', '\u{0}']), ('\u{a64d}', ['\u{a64c}', '\u{0}', '\u{0}']),
+        ('\u{a64f}', ['\u{a64e}', '\u{0}', '\u{0}']), ('\u{a651}', ['\u{a650}', '\u{0}', '\u{0}']),
+        ('\u{a653}', ['\u{a652}', '\u{0}', '\u{0}']), ('\u{a655}', ['\u{a654}', '\u{0}', '\u{0}']),
+        ('\u{a657}', ['\u{a656}', '\u{0}', '\u{0}']), ('\u{a659}', ['\u{a658}', '\u{0}', '\u{0}']),
+        ('\u{a65b}', ['\u{a65a}', '\u{0}', '\u{0}']), ('\u{a65d}', ['\u{a65c}', '\u{0}', '\u{0}']),
+        ('\u{a65f}', ['\u{a65e}', '\u{0}', '\u{0}']), ('\u{a661}', ['\u{a660}', '\u{0}', '\u{0}']),
+        ('\u{a663}', ['\u{a662}', '\u{0}', '\u{0}']), ('\u{a665}', ['\u{a664}', '\u{0}', '\u{0}']),
+        ('\u{a667}', ['\u{a666}', '\u{0}', '\u{0}']), ('\u{a669}', ['\u{a668}', '\u{0}', '\u{0}']),
+        ('\u{a66b}', ['\u{a66a}', '\u{0}', '\u{0}']), ('\u{a66d}', ['\u{a66c}', '\u{0}', '\u{0}']),
+        ('\u{a681}', ['\u{a680}', '\u{0}', '\u{0}']), ('\u{a683}', ['\u{a682}', '\u{0}', '\u{0}']),
+        ('\u{a685}', ['\u{a684}', '\u{0}', '\u{0}']), ('\u{a687}', ['\u{a686}', '\u{0}', '\u{0}']),
+        ('\u{a689}', ['\u{a688}', '\u{0}', '\u{0}']), ('\u{a68b}', ['\u{a68a}', '\u{0}', '\u{0}']),
+        ('\u{a68d}', ['\u{a68c}', '\u{0}', '\u{0}']), ('\u{a68f}', ['\u{a68e}', '\u{0}', '\u{0}']),
+        ('\u{a691}', ['\u{a690}', '\u{0}', '\u{0}']), ('\u{a693}', ['\u{a692}', '\u{0}', '\u{0}']),
+        ('\u{a695}', ['\u{a694}', '\u{0}', '\u{0}']), ('\u{a697}', ['\u{a696}', '\u{0}', '\u{0}']),
+        ('\u{a699}', ['\u{a698}', '\u{0}', '\u{0}']), ('\u{a69b}', ['\u{a69a}', '\u{0}', '\u{0}']),
+        ('\u{a723}', ['\u{a722}', '\u{0}', '\u{0}']), ('\u{a725}', ['\u{a724}', '\u{0}', '\u{0}']),
+        ('\u{a727}', ['\u{a726}', '\u{0}', '\u{0}']), ('\u{a729}', ['\u{a728}', '\u{0}', '\u{0}']),
+        ('\u{a72b}', ['\u{a72a}', '\u{0}', '\u{0}']), ('\u{a72d}', ['\u{a72c}', '\u{0}', '\u{0}']),
+        ('\u{a72f}', ['\u{a72e}', '\u{0}', '\u{0}']), ('\u{a733}', ['\u{a732}', '\u{0}', '\u{0}']),
+        ('\u{a735}', ['\u{a734}', '\u{0}', '\u{0}']), ('\u{a737}', ['\u{a736}', '\u{0}', '\u{0}']),
+        ('\u{a739}', ['\u{a738}', '\u{0}', '\u{0}']), ('\u{a73b}', ['\u{a73a}', '\u{0}', '\u{0}']),
+        ('\u{a73d}', ['\u{a73c}', '\u{0}', '\u{0}']), ('\u{a73f}', ['\u{a73e}', '\u{0}', '\u{0}']),
+        ('\u{a741}', ['\u{a740}', '\u{0}', '\u{0}']), ('\u{a743}', ['\u{a742}', '\u{0}', '\u{0}']),
+        ('\u{a745}', ['\u{a744}', '\u{0}', '\u{0}']), ('\u{a747}', ['\u{a746}', '\u{0}', '\u{0}']),
+        ('\u{a749}', ['\u{a748}', '\u{0}', '\u{0}']), ('\u{a74b}', ['\u{a74a}', '\u{0}', '\u{0}']),
+        ('\u{a74d}', ['\u{a74c}', '\u{0}', '\u{0}']), ('\u{a74f}', ['\u{a74e}', '\u{0}', '\u{0}']),
+        ('\u{a751}', ['\u{a750}', '\u{0}', '\u{0}']), ('\u{a753}', ['\u{a752}', '\u{0}', '\u{0}']),
+        ('\u{a755}', ['\u{a754}', '\u{0}', '\u{0}']), ('\u{a757}', ['\u{a756}', '\u{0}', '\u{0}']),
+        ('\u{a759}', ['\u{a758}', '\u{0}', '\u{0}']), ('\u{a75b}', ['\u{a75a}', '\u{0}', '\u{0}']),
+        ('\u{a75d}', ['\u{a75c}', '\u{0}', '\u{0}']), ('\u{a75f}', ['\u{a75e}', '\u{0}', '\u{0}']),
+        ('\u{a761}', ['\u{a760}', '\u{0}', '\u{0}']), ('\u{a763}', ['\u{a762}', '\u{0}', '\u{0}']),
+        ('\u{a765}', ['\u{a764}', '\u{0}', '\u{0}']), ('\u{a767}', ['\u{a766}', '\u{0}', '\u{0}']),
+        ('\u{a769}', ['\u{a768}', '\u{0}', '\u{0}']), ('\u{a76b}', ['\u{a76a}', '\u{0}', '\u{0}']),
+        ('\u{a76d}', ['\u{a76c}', '\u{0}', '\u{0}']), ('\u{a76f}', ['\u{a76e}', '\u{0}', '\u{0}']),
+        ('\u{a77a}', ['\u{a779}', '\u{0}', '\u{0}']), ('\u{a77c}', ['\u{a77b}', '\u{0}', '\u{0}']),
+        ('\u{a77f}', ['\u{a77e}', '\u{0}', '\u{0}']), ('\u{a781}', ['\u{a780}', '\u{0}', '\u{0}']),
+        ('\u{a783}', ['\u{a782}', '\u{0}', '\u{0}']), ('\u{a785}', ['\u{a784}', '\u{0}', '\u{0}']),
+        ('\u{a787}', ['\u{a786}', '\u{0}', '\u{0}']), ('\u{a78c}', ['\u{a78b}', '\u{0}', '\u{0}']),
+        ('\u{a791}', ['\u{a790}', '\u{0}', '\u{0}']), ('\u{a793}', ['\u{a792}', '\u{0}', '\u{0}']),
+        ('\u{a794}', ['\u{a7c4}', '\u{0}', '\u{0}']), ('\u{a797}', ['\u{a796}', '\u{0}', '\u{0}']),
+        ('\u{a799}', ['\u{a798}', '\u{0}', '\u{0}']), ('\u{a79b}', ['\u{a79a}', '\u{0}', '\u{0}']),
+        ('\u{a79d}', ['\u{a79c}', '\u{0}', '\u{0}']), ('\u{a79f}', ['\u{a79e}', '\u{0}', '\u{0}']),
+        ('\u{a7a1}', ['\u{a7a0}', '\u{0}', '\u{0}']), ('\u{a7a3}', ['\u{a7a2}', '\u{0}', '\u{0}']),
+        ('\u{a7a5}', ['\u{a7a4}', '\u{0}', '\u{0}']), ('\u{a7a7}', ['\u{a7a6}', '\u{0}', '\u{0}']),
+        ('\u{a7a9}', ['\u{a7a8}', '\u{0}', '\u{0}']), ('\u{a7b5}', ['\u{a7b4}', '\u{0}', '\u{0}']),
+        ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']),
+        ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']),
+        ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']),
+        ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']),
+        ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']),
+        ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']),
+        ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']),
+        ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']),
+        ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']),
+        ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']),
+        ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']),
+        ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']),
+        ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']),
+        ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']),
+        ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']),
+        ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']),
+        ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']),
+        ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']),
+        ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']),
+        ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']),
+        ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']),
+        ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']),
+        ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']),
+        ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']),
+        ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']),
+        ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']),
+        ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']),
+        ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']),
+        ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']),
+        ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']),
+        ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']),
+        ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']),
+        ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']),
+        ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']),
+        ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']),
+        ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']),
+        ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']),
+        ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']),
+        ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']),
+        ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']),
+        ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']),
+        ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']),
+        ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']),
+        ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'F', '\u{0}']),
+        ('\u{fb01}', ['F', 'I', '\u{0}']), ('\u{fb02}', ['F', 'L', '\u{0}']),
+        ('\u{fb03}', ['F', 'F', 'I']), ('\u{fb04}', ['F', 'F', 'L']),
+        ('\u{fb05}', ['S', 'T', '\u{0}']), ('\u{fb06}', ['S', 'T', '\u{0}']),
+        ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']),
+        ('\u{fb14}', ['\u{544}', '\u{535}', '\u{0}']),
+        ('\u{fb15}', ['\u{544}', '\u{53b}', '\u{0}']),
+        ('\u{fb16}', ['\u{54e}', '\u{546}', '\u{0}']),
+        ('\u{fb17}', ['\u{544}', '\u{53d}', '\u{0}']), ('\u{ff41}', ['\u{ff21}', '\u{0}', '\u{0}']),
+        ('\u{ff42}', ['\u{ff22}', '\u{0}', '\u{0}']), ('\u{ff43}', ['\u{ff23}', '\u{0}', '\u{0}']),
+        ('\u{ff44}', ['\u{ff24}', '\u{0}', '\u{0}']), ('\u{ff45}', ['\u{ff25}', '\u{0}', '\u{0}']),
+        ('\u{ff46}', ['\u{ff26}', '\u{0}', '\u{0}']), ('\u{ff47}', ['\u{ff27}', '\u{0}', '\u{0}']),
+        ('\u{ff48}', ['\u{ff28}', '\u{0}', '\u{0}']), ('\u{ff49}', ['\u{ff29}', '\u{0}', '\u{0}']),
+        ('\u{ff4a}', ['\u{ff2a}', '\u{0}', '\u{0}']), ('\u{ff4b}', ['\u{ff2b}', '\u{0}', '\u{0}']),
+        ('\u{ff4c}', ['\u{ff2c}', '\u{0}', '\u{0}']), ('\u{ff4d}', ['\u{ff2d}', '\u{0}', '\u{0}']),
+        ('\u{ff4e}', ['\u{ff2e}', '\u{0}', '\u{0}']), ('\u{ff4f}', ['\u{ff2f}', '\u{0}', '\u{0}']),
+        ('\u{ff50}', ['\u{ff30}', '\u{0}', '\u{0}']), ('\u{ff51}', ['\u{ff31}', '\u{0}', '\u{0}']),
+        ('\u{ff52}', ['\u{ff32}', '\u{0}', '\u{0}']), ('\u{ff53}', ['\u{ff33}', '\u{0}', '\u{0}']),
+        ('\u{ff54}', ['\u{ff34}', '\u{0}', '\u{0}']), ('\u{ff55}', ['\u{ff35}', '\u{0}', '\u{0}']),
+        ('\u{ff56}', ['\u{ff36}', '\u{0}', '\u{0}']), ('\u{ff57}', ['\u{ff37}', '\u{0}', '\u{0}']),
+        ('\u{ff58}', ['\u{ff38}', '\u{0}', '\u{0}']), ('\u{ff59}', ['\u{ff39}', '\u{0}', '\u{0}']),
+        ('\u{ff5a}', ['\u{ff3a}', '\u{0}', '\u{0}']),
+        ('\u{10428}', ['\u{10400}', '\u{0}', '\u{0}']),
+        ('\u{10429}', ['\u{10401}', '\u{0}', '\u{0}']),
+        ('\u{1042a}', ['\u{10402}', '\u{0}', '\u{0}']),
+        ('\u{1042b}', ['\u{10403}', '\u{0}', '\u{0}']),
+        ('\u{1042c}', ['\u{10404}', '\u{0}', '\u{0}']),
+        ('\u{1042d}', ['\u{10405}', '\u{0}', '\u{0}']),
+        ('\u{1042e}', ['\u{10406}', '\u{0}', '\u{0}']),
+        ('\u{1042f}', ['\u{10407}', '\u{0}', '\u{0}']),
+        ('\u{10430}', ['\u{10408}', '\u{0}', '\u{0}']),
+        ('\u{10431}', ['\u{10409}', '\u{0}', '\u{0}']),
+        ('\u{10432}', ['\u{1040a}', '\u{0}', '\u{0}']),
+        ('\u{10433}', ['\u{1040b}', '\u{0}', '\u{0}']),
+        ('\u{10434}', ['\u{1040c}', '\u{0}', '\u{0}']),
+        ('\u{10435}', ['\u{1040d}', '\u{0}', '\u{0}']),
+        ('\u{10436}', ['\u{1040e}', '\u{0}', '\u{0}']),
+        ('\u{10437}', ['\u{1040f}', '\u{0}', '\u{0}']),
+        ('\u{10438}', ['\u{10410}', '\u{0}', '\u{0}']),
+        ('\u{10439}', ['\u{10411}', '\u{0}', '\u{0}']),
+        ('\u{1043a}', ['\u{10412}', '\u{0}', '\u{0}']),
+        ('\u{1043b}', ['\u{10413}', '\u{0}', '\u{0}']),
+        ('\u{1043c}', ['\u{10414}', '\u{0}', '\u{0}']),
+        ('\u{1043d}', ['\u{10415}', '\u{0}', '\u{0}']),
+        ('\u{1043e}', ['\u{10416}', '\u{0}', '\u{0}']),
+        ('\u{1043f}', ['\u{10417}', '\u{0}', '\u{0}']),
+        ('\u{10440}', ['\u{10418}', '\u{0}', '\u{0}']),
+        ('\u{10441}', ['\u{10419}', '\u{0}', '\u{0}']),
+        ('\u{10442}', ['\u{1041a}', '\u{0}', '\u{0}']),
+        ('\u{10443}', ['\u{1041b}', '\u{0}', '\u{0}']),
+        ('\u{10444}', ['\u{1041c}', '\u{0}', '\u{0}']),
+        ('\u{10445}', ['\u{1041d}', '\u{0}', '\u{0}']),
+        ('\u{10446}', ['\u{1041e}', '\u{0}', '\u{0}']),
+        ('\u{10447}', ['\u{1041f}', '\u{0}', '\u{0}']),
+        ('\u{10448}', ['\u{10420}', '\u{0}', '\u{0}']),
+        ('\u{10449}', ['\u{10421}', '\u{0}', '\u{0}']),
+        ('\u{1044a}', ['\u{10422}', '\u{0}', '\u{0}']),
+        ('\u{1044b}', ['\u{10423}', '\u{0}', '\u{0}']),
+        ('\u{1044c}', ['\u{10424}', '\u{0}', '\u{0}']),
+        ('\u{1044d}', ['\u{10425}', '\u{0}', '\u{0}']),
+        ('\u{1044e}', ['\u{10426}', '\u{0}', '\u{0}']),
+        ('\u{1044f}', ['\u{10427}', '\u{0}', '\u{0}']),
+        ('\u{104d8}', ['\u{104b0}', '\u{0}', '\u{0}']),
+        ('\u{104d9}', ['\u{104b1}', '\u{0}', '\u{0}']),
+        ('\u{104da}', ['\u{104b2}', '\u{0}', '\u{0}']),
+        ('\u{104db}', ['\u{104b3}', '\u{0}', '\u{0}']),
+        ('\u{104dc}', ['\u{104b4}', '\u{0}', '\u{0}']),
+        ('\u{104dd}', ['\u{104b5}', '\u{0}', '\u{0}']),
+        ('\u{104de}', ['\u{104b6}', '\u{0}', '\u{0}']),
+        ('\u{104df}', ['\u{104b7}', '\u{0}', '\u{0}']),
+        ('\u{104e0}', ['\u{104b8}', '\u{0}', '\u{0}']),
+        ('\u{104e1}', ['\u{104b9}', '\u{0}', '\u{0}']),
+        ('\u{104e2}', ['\u{104ba}', '\u{0}', '\u{0}']),
+        ('\u{104e3}', ['\u{104bb}', '\u{0}', '\u{0}']),
+        ('\u{104e4}', ['\u{104bc}', '\u{0}', '\u{0}']),
+        ('\u{104e5}', ['\u{104bd}', '\u{0}', '\u{0}']),
+        ('\u{104e6}', ['\u{104be}', '\u{0}', '\u{0}']),
+        ('\u{104e7}', ['\u{104bf}', '\u{0}', '\u{0}']),
+        ('\u{104e8}', ['\u{104c0}', '\u{0}', '\u{0}']),
+        ('\u{104e9}', ['\u{104c1}', '\u{0}', '\u{0}']),
+        ('\u{104ea}', ['\u{104c2}', '\u{0}', '\u{0}']),
+        ('\u{104eb}', ['\u{104c3}', '\u{0}', '\u{0}']),
+        ('\u{104ec}', ['\u{104c4}', '\u{0}', '\u{0}']),
+        ('\u{104ed}', ['\u{104c5}', '\u{0}', '\u{0}']),
+        ('\u{104ee}', ['\u{104c6}', '\u{0}', '\u{0}']),
+        ('\u{104ef}', ['\u{104c7}', '\u{0}', '\u{0}']),
+        ('\u{104f0}', ['\u{104c8}', '\u{0}', '\u{0}']),
+        ('\u{104f1}', ['\u{104c9}', '\u{0}', '\u{0}']),
+        ('\u{104f2}', ['\u{104ca}', '\u{0}', '\u{0}']),
+        ('\u{104f3}', ['\u{104cb}', '\u{0}', '\u{0}']),
+        ('\u{104f4}', ['\u{104cc}', '\u{0}', '\u{0}']),
+        ('\u{104f5}', ['\u{104cd}', '\u{0}', '\u{0}']),
+        ('\u{104f6}', ['\u{104ce}', '\u{0}', '\u{0}']),
+        ('\u{104f7}', ['\u{104cf}', '\u{0}', '\u{0}']),
+        ('\u{104f8}', ['\u{104d0}', '\u{0}', '\u{0}']),
+        ('\u{104f9}', ['\u{104d1}', '\u{0}', '\u{0}']),
+        ('\u{104fa}', ['\u{104d2}', '\u{0}', '\u{0}']),
+        ('\u{104fb}', ['\u{104d3}', '\u{0}', '\u{0}']),
+        ('\u{10cc0}', ['\u{10c80}', '\u{0}', '\u{0}']),
+        ('\u{10cc1}', ['\u{10c81}', '\u{0}', '\u{0}']),
+        ('\u{10cc2}', ['\u{10c82}', '\u{0}', '\u{0}']),
+        ('\u{10cc3}', ['\u{10c83}', '\u{0}', '\u{0}']),
+        ('\u{10cc4}', ['\u{10c84}', '\u{0}', '\u{0}']),
+        ('\u{10cc5}', ['\u{10c85}', '\u{0}', '\u{0}']),
+        ('\u{10cc6}', ['\u{10c86}', '\u{0}', '\u{0}']),
+        ('\u{10cc7}', ['\u{10c87}', '\u{0}', '\u{0}']),
+        ('\u{10cc8}', ['\u{10c88}', '\u{0}', '\u{0}']),
+        ('\u{10cc9}', ['\u{10c89}', '\u{0}', '\u{0}']),
+        ('\u{10cca}', ['\u{10c8a}', '\u{0}', '\u{0}']),
+        ('\u{10ccb}', ['\u{10c8b}', '\u{0}', '\u{0}']),
+        ('\u{10ccc}', ['\u{10c8c}', '\u{0}', '\u{0}']),
+        ('\u{10ccd}', ['\u{10c8d}', '\u{0}', '\u{0}']),
+        ('\u{10cce}', ['\u{10c8e}', '\u{0}', '\u{0}']),
+        ('\u{10ccf}', ['\u{10c8f}', '\u{0}', '\u{0}']),
+        ('\u{10cd0}', ['\u{10c90}', '\u{0}', '\u{0}']),
+        ('\u{10cd1}', ['\u{10c91}', '\u{0}', '\u{0}']),
+        ('\u{10cd2}', ['\u{10c92}', '\u{0}', '\u{0}']),
+        ('\u{10cd3}', ['\u{10c93}', '\u{0}', '\u{0}']),
+        ('\u{10cd4}', ['\u{10c94}', '\u{0}', '\u{0}']),
+        ('\u{10cd5}', ['\u{10c95}', '\u{0}', '\u{0}']),
+        ('\u{10cd6}', ['\u{10c96}', '\u{0}', '\u{0}']),
+        ('\u{10cd7}', ['\u{10c97}', '\u{0}', '\u{0}']),
+        ('\u{10cd8}', ['\u{10c98}', '\u{0}', '\u{0}']),
+        ('\u{10cd9}', ['\u{10c99}', '\u{0}', '\u{0}']),
+        ('\u{10cda}', ['\u{10c9a}', '\u{0}', '\u{0}']),
+        ('\u{10cdb}', ['\u{10c9b}', '\u{0}', '\u{0}']),
+        ('\u{10cdc}', ['\u{10c9c}', '\u{0}', '\u{0}']),
+        ('\u{10cdd}', ['\u{10c9d}', '\u{0}', '\u{0}']),
+        ('\u{10cde}', ['\u{10c9e}', '\u{0}', '\u{0}']),
+        ('\u{10cdf}', ['\u{10c9f}', '\u{0}', '\u{0}']),
+        ('\u{10ce0}', ['\u{10ca0}', '\u{0}', '\u{0}']),
+        ('\u{10ce1}', ['\u{10ca1}', '\u{0}', '\u{0}']),
+        ('\u{10ce2}', ['\u{10ca2}', '\u{0}', '\u{0}']),
+        ('\u{10ce3}', ['\u{10ca3}', '\u{0}', '\u{0}']),
+        ('\u{10ce4}', ['\u{10ca4}', '\u{0}', '\u{0}']),
+        ('\u{10ce5}', ['\u{10ca5}', '\u{0}', '\u{0}']),
+        ('\u{10ce6}', ['\u{10ca6}', '\u{0}', '\u{0}']),
+        ('\u{10ce7}', ['\u{10ca7}', '\u{0}', '\u{0}']),
+        ('\u{10ce8}', ['\u{10ca8}', '\u{0}', '\u{0}']),
+        ('\u{10ce9}', ['\u{10ca9}', '\u{0}', '\u{0}']),
+        ('\u{10cea}', ['\u{10caa}', '\u{0}', '\u{0}']),
+        ('\u{10ceb}', ['\u{10cab}', '\u{0}', '\u{0}']),
+        ('\u{10cec}', ['\u{10cac}', '\u{0}', '\u{0}']),
+        ('\u{10ced}', ['\u{10cad}', '\u{0}', '\u{0}']),
+        ('\u{10cee}', ['\u{10cae}', '\u{0}', '\u{0}']),
+        ('\u{10cef}', ['\u{10caf}', '\u{0}', '\u{0}']),
+        ('\u{10cf0}', ['\u{10cb0}', '\u{0}', '\u{0}']),
+        ('\u{10cf1}', ['\u{10cb1}', '\u{0}', '\u{0}']),
+        ('\u{10cf2}', ['\u{10cb2}', '\u{0}', '\u{0}']),
+        ('\u{118c0}', ['\u{118a0}', '\u{0}', '\u{0}']),
+        ('\u{118c1}', ['\u{118a1}', '\u{0}', '\u{0}']),
+        ('\u{118c2}', ['\u{118a2}', '\u{0}', '\u{0}']),
+        ('\u{118c3}', ['\u{118a3}', '\u{0}', '\u{0}']),
+        ('\u{118c4}', ['\u{118a4}', '\u{0}', '\u{0}']),
+        ('\u{118c5}', ['\u{118a5}', '\u{0}', '\u{0}']),
+        ('\u{118c6}', ['\u{118a6}', '\u{0}', '\u{0}']),
+        ('\u{118c7}', ['\u{118a7}', '\u{0}', '\u{0}']),
+        ('\u{118c8}', ['\u{118a8}', '\u{0}', '\u{0}']),
+        ('\u{118c9}', ['\u{118a9}', '\u{0}', '\u{0}']),
+        ('\u{118ca}', ['\u{118aa}', '\u{0}', '\u{0}']),
+        ('\u{118cb}', ['\u{118ab}', '\u{0}', '\u{0}']),
+        ('\u{118cc}', ['\u{118ac}', '\u{0}', '\u{0}']),
+        ('\u{118cd}', ['\u{118ad}', '\u{0}', '\u{0}']),
+        ('\u{118ce}', ['\u{118ae}', '\u{0}', '\u{0}']),
+        ('\u{118cf}', ['\u{118af}', '\u{0}', '\u{0}']),
+        ('\u{118d0}', ['\u{118b0}', '\u{0}', '\u{0}']),
+        ('\u{118d1}', ['\u{118b1}', '\u{0}', '\u{0}']),
+        ('\u{118d2}', ['\u{118b2}', '\u{0}', '\u{0}']),
+        ('\u{118d3}', ['\u{118b3}', '\u{0}', '\u{0}']),
+        ('\u{118d4}', ['\u{118b4}', '\u{0}', '\u{0}']),
+        ('\u{118d5}', ['\u{118b5}', '\u{0}', '\u{0}']),
+        ('\u{118d6}', ['\u{118b6}', '\u{0}', '\u{0}']),
+        ('\u{118d7}', ['\u{118b7}', '\u{0}', '\u{0}']),
+        ('\u{118d8}', ['\u{118b8}', '\u{0}', '\u{0}']),
+        ('\u{118d9}', ['\u{118b9}', '\u{0}', '\u{0}']),
+        ('\u{118da}', ['\u{118ba}', '\u{0}', '\u{0}']),
+        ('\u{118db}', ['\u{118bb}', '\u{0}', '\u{0}']),
+        ('\u{118dc}', ['\u{118bc}', '\u{0}', '\u{0}']),
+        ('\u{118dd}', ['\u{118bd}', '\u{0}', '\u{0}']),
+        ('\u{118de}', ['\u{118be}', '\u{0}', '\u{0}']),
+        ('\u{118df}', ['\u{118bf}', '\u{0}', '\u{0}']),
+        ('\u{16e60}', ['\u{16e40}', '\u{0}', '\u{0}']),
+        ('\u{16e61}', ['\u{16e41}', '\u{0}', '\u{0}']),
+        ('\u{16e62}', ['\u{16e42}', '\u{0}', '\u{0}']),
+        ('\u{16e63}', ['\u{16e43}', '\u{0}', '\u{0}']),
+        ('\u{16e64}', ['\u{16e44}', '\u{0}', '\u{0}']),
+        ('\u{16e65}', ['\u{16e45}', '\u{0}', '\u{0}']),
+        ('\u{16e66}', ['\u{16e46}', '\u{0}', '\u{0}']),
+        ('\u{16e67}', ['\u{16e47}', '\u{0}', '\u{0}']),
+        ('\u{16e68}', ['\u{16e48}', '\u{0}', '\u{0}']),
+        ('\u{16e69}', ['\u{16e49}', '\u{0}', '\u{0}']),
+        ('\u{16e6a}', ['\u{16e4a}', '\u{0}', '\u{0}']),
+        ('\u{16e6b}', ['\u{16e4b}', '\u{0}', '\u{0}']),
+        ('\u{16e6c}', ['\u{16e4c}', '\u{0}', '\u{0}']),
+        ('\u{16e6d}', ['\u{16e4d}', '\u{0}', '\u{0}']),
+        ('\u{16e6e}', ['\u{16e4e}', '\u{0}', '\u{0}']),
+        ('\u{16e6f}', ['\u{16e4f}', '\u{0}', '\u{0}']),
+        ('\u{16e70}', ['\u{16e50}', '\u{0}', '\u{0}']),
+        ('\u{16e71}', ['\u{16e51}', '\u{0}', '\u{0}']),
+        ('\u{16e72}', ['\u{16e52}', '\u{0}', '\u{0}']),
+        ('\u{16e73}', ['\u{16e53}', '\u{0}', '\u{0}']),
+        ('\u{16e74}', ['\u{16e54}', '\u{0}', '\u{0}']),
+        ('\u{16e75}', ['\u{16e55}', '\u{0}', '\u{0}']),
+        ('\u{16e76}', ['\u{16e56}', '\u{0}', '\u{0}']),
+        ('\u{16e77}', ['\u{16e57}', '\u{0}', '\u{0}']),
+        ('\u{16e78}', ['\u{16e58}', '\u{0}', '\u{0}']),
+        ('\u{16e79}', ['\u{16e59}', '\u{0}', '\u{0}']),
+        ('\u{16e7a}', ['\u{16e5a}', '\u{0}', '\u{0}']),
+        ('\u{16e7b}', ['\u{16e5b}', '\u{0}', '\u{0}']),
+        ('\u{16e7c}', ['\u{16e5c}', '\u{0}', '\u{0}']),
+        ('\u{16e7d}', ['\u{16e5d}', '\u{0}', '\u{0}']),
+        ('\u{16e7e}', ['\u{16e5e}', '\u{0}', '\u{0}']),
+        ('\u{16e7f}', ['\u{16e5f}', '\u{0}', '\u{0}']),
+        ('\u{1e922}', ['\u{1e900}', '\u{0}', '\u{0}']),
+        ('\u{1e923}', ['\u{1e901}', '\u{0}', '\u{0}']),
+        ('\u{1e924}', ['\u{1e902}', '\u{0}', '\u{0}']),
+        ('\u{1e925}', ['\u{1e903}', '\u{0}', '\u{0}']),
+        ('\u{1e926}', ['\u{1e904}', '\u{0}', '\u{0}']),
+        ('\u{1e927}', ['\u{1e905}', '\u{0}', '\u{0}']),
+        ('\u{1e928}', ['\u{1e906}', '\u{0}', '\u{0}']),
+        ('\u{1e929}', ['\u{1e907}', '\u{0}', '\u{0}']),
+        ('\u{1e92a}', ['\u{1e908}', '\u{0}', '\u{0}']),
+        ('\u{1e92b}', ['\u{1e909}', '\u{0}', '\u{0}']),
+        ('\u{1e92c}', ['\u{1e90a}', '\u{0}', '\u{0}']),
+        ('\u{1e92d}', ['\u{1e90b}', '\u{0}', '\u{0}']),
+        ('\u{1e92e}', ['\u{1e90c}', '\u{0}', '\u{0}']),
+        ('\u{1e92f}', ['\u{1e90d}', '\u{0}', '\u{0}']),
+        ('\u{1e930}', ['\u{1e90e}', '\u{0}', '\u{0}']),
+        ('\u{1e931}', ['\u{1e90f}', '\u{0}', '\u{0}']),
+        ('\u{1e932}', ['\u{1e910}', '\u{0}', '\u{0}']),
+        ('\u{1e933}', ['\u{1e911}', '\u{0}', '\u{0}']),
+        ('\u{1e934}', ['\u{1e912}', '\u{0}', '\u{0}']),
+        ('\u{1e935}', ['\u{1e913}', '\u{0}', '\u{0}']),
+        ('\u{1e936}', ['\u{1e914}', '\u{0}', '\u{0}']),
+        ('\u{1e937}', ['\u{1e915}', '\u{0}', '\u{0}']),
+        ('\u{1e938}', ['\u{1e916}', '\u{0}', '\u{0}']),
+        ('\u{1e939}', ['\u{1e917}', '\u{0}', '\u{0}']),
+        ('\u{1e93a}', ['\u{1e918}', '\u{0}', '\u{0}']),
+        ('\u{1e93b}', ['\u{1e919}', '\u{0}', '\u{0}']),
+        ('\u{1e93c}', ['\u{1e91a}', '\u{0}', '\u{0}']),
+        ('\u{1e93d}', ['\u{1e91b}', '\u{0}', '\u{0}']),
+        ('\u{1e93e}', ['\u{1e91c}', '\u{0}', '\u{0}']),
+        ('\u{1e93f}', ['\u{1e91d}', '\u{0}', '\u{0}']),
+        ('\u{1e940}', ['\u{1e91e}', '\u{0}', '\u{0}']),
+        ('\u{1e941}', ['\u{1e91f}', '\u{0}', '\u{0}']),
+        ('\u{1e942}', ['\u{1e920}', '\u{0}', '\u{0}']),
+        ('\u{1e943}', ['\u{1e921}', '\u{0}', '\u{0}']),
+    ];
+}
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index 2098404..9161d49 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -52,22 +52,49 @@
     ptr::null_mut()
 }
 
+struct Exception {
+    // This needs to be an Option because the object's lifetime follows C++
+    // semantics: when catch_unwind moves the Box out of the exception it must
+    // still leave the exception object in a valid state because its destructor
+    // is still going to be called by __cxa_end_catch..
+    data: Option<Box<dyn Any + Send>>,
+}
+
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     assert!(!ptr.is_null());
-    let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void);
-    let ex = ptr::read(adjusted_ptr as *mut _);
+    let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void) as *mut Exception;
+    let ex = (*adjusted_ptr).data.take();
     __cxa_end_catch();
-    ex
+    ex.unwrap()
 }
 
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     let sz = mem::size_of_val(&data);
-    let exception = __cxa_allocate_exception(sz);
-    if exception == ptr::null_mut() {
+    let exception = __cxa_allocate_exception(sz) as *mut Exception;
+    if exception.is_null() {
         return uw::_URC_FATAL_PHASE1_ERROR as u32;
     }
-    ptr::write(exception as *mut _, data);
-    __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, ptr::null_mut());
+    ptr::write(exception, Exception { data: Some(data) });
+    __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
+}
+
+// On WASM and ARM, the destructor returns the pointer to the object.
+cfg_if::cfg_if! {
+    if #[cfg(any(target_arch = "arm", target_arch = "wasm32"))] {
+        type DestructorRet = *mut libc::c_void;
+    } else {
+        type DestructorRet = ();
+    }
+}
+extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> DestructorRet {
+    unsafe {
+        if let Some(b) = (ptr as *mut Exception).read().data {
+            drop(b);
+            super::__rust_drop_panic();
+        }
+        #[cfg(any(target_arch = "arm", target_arch = "wasm32"))]
+        ptr
+    }
 }
 
 #[lang = "eh_personality"]
@@ -89,7 +116,7 @@
     fn __cxa_throw(
         thrown_exception: *mut libc::c_void,
         tinfo: *const TypeInfo,
-        dest: *mut libc::c_void,
+        dest: extern "C" fn(*mut libc::c_void) -> DestructorRet,
     ) -> !;
     fn __gxx_personality_v0(
         version: c_int,
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 6a48fa0..591ff9d 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -4,7 +4,7 @@
 //! "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and
 //! documents linked from it.
 //! These are also good reads:
-//!     http://mentorembedded.github.io/cxx-abi/abi-eh.html
+//!     https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
 //!     http://monoinfinito.wordpress.com/series/exception-handling-in-c/
 //!     http://www.airs.com/blog/index.php?s=exception+frames
 //!
@@ -57,7 +57,7 @@
 #[repr(C)]
 struct Exception {
     _uwe: uw::_Unwind_Exception,
-    cause: Option<Box<dyn Any + Send>>,
+    cause: Box<dyn Any + Send>,
 }
 
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
@@ -67,7 +67,7 @@
             exception_cleanup,
             private: [0; uw::unwinder_private_data_size],
         },
-        cause: Some(data),
+        cause: data,
     });
     let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
     return uw::_Unwind_RaiseException(exception_param) as u32;
@@ -78,6 +78,7 @@
     ) {
         unsafe {
             let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
+            super::__rust_drop_panic();
         }
     }
 }
@@ -87,10 +88,8 @@
 }
 
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
-    let my_ep = ptr as *mut Exception;
-    let cause = (*my_ep).cause.take();
-    uw::_Unwind_DeleteException(ptr as *mut _);
-    cause.unwrap()
+    let exception = Box::from_raw(ptr as *mut Exception);
+    exception.cause
 }
 
 // Rust's exception class identifier.  This is used by personality routines to
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index e721162..6383ae3 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -26,6 +26,7 @@
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(unwind_attributes)]
+#![feature(abi_thiscall)]
 #![panic_runtime]
 #![feature(panic_runtime)]
 
@@ -60,6 +61,12 @@
     }
 }
 
+extern "C" {
+    /// Handler in libstd called when a panic object is dropped outside of
+    /// `catch_unwind`.
+    fn __rust_drop_panic() -> !;
+}
+
 mod dwarf;
 
 // Entry point for catching an exception, implemented using the `try` intrinsic
diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs
index e1907ec..d9dca2c 100644
--- a/src/libpanic_unwind/seh.rs
+++ b/src/libpanic_unwind/seh.rs
@@ -77,8 +77,11 @@
 //      #include <stdint.h>
 //
 //      struct rust_panic {
+//          rust_panic(const rust_panic&);
+//          ~rust_panic();
+//
 //          uint64_t x[2];
-//      }
+//      };
 //
 //      void foo() {
 //          rust_panic a = {0, 1};
@@ -128,7 +131,7 @@
 #[repr(C)]
 pub struct _ThrowInfo {
     pub attributes: c_uint,
-    pub pnfnUnwind: imp::ptr_t,
+    pub pmfnUnwind: imp::ptr_t,
     pub pForwardCompat: imp::ptr_t,
     pub pCatchableTypeArray: imp::ptr_t,
 }
@@ -145,7 +148,7 @@
     pub pType: imp::ptr_t,
     pub thisDisplacement: _PMD,
     pub sizeOrOffset: c_int,
-    pub copy_function: imp::ptr_t,
+    pub copyFunction: imp::ptr_t,
 }
 
 #[repr(C)]
@@ -168,7 +171,7 @@
 
 static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
     attributes: 0,
-    pnfnUnwind: ptr!(0),
+    pmfnUnwind: ptr!(0),
     pForwardCompat: ptr!(0),
     pCatchableTypeArray: ptr!(0),
 };
@@ -181,7 +184,7 @@
     pType: ptr!(0),
     thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 },
     sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int,
-    copy_function: ptr!(0),
+    copyFunction: ptr!(0),
 };
 
 extern "C" {
@@ -208,6 +211,43 @@
     name: TYPE_NAME,
 };
 
+// Destructor used if the C++ code decides to capture the exception and drop it
+// without propagating it. The catch part of the try intrinsic will set the
+// first word of the exception object to 0 so that it is skipped by the
+// destructor.
+//
+// Note that x86 Windows uses the "thiscall" calling convention for C++ member
+// functions instead of the default "C" calling convention.
+//
+// The exception_copy function is a bit special here: it is invoked by the MSVC
+// runtime under a try/catch block and the panic that we generate here will be
+// used as the result of the exception copy. This is used by the C++ runtime to
+// support capturing exceptions with std::exception_ptr, which we can't support
+// because Box<dyn Any> isn't clonable.
+macro_rules! define_cleanup {
+    ($abi:tt) => {
+        unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
+            if (*e)[0] != 0 {
+                cleanup(*e);
+                super::__rust_drop_panic();
+            }
+        }
+        #[unwind(allowed)]
+        unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2],
+                                             _src: *mut [u64; 2])
+                                             -> *mut [u64; 2] {
+            panic!("Rust panics cannot be copied");
+        }
+    }
+}
+cfg_if::cfg_if! {
+   if #[cfg(target_arch = "x86")] {
+       define_cleanup!("thiscall");
+   } else {
+       define_cleanup!("C");
+   }
+}
+
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     use core::intrinsics::atomic_store;
 
@@ -220,8 +260,7 @@
     // exception (constructed above).
     let ptrs = mem::transmute::<_, raw::TraitObject>(data);
     let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64];
-    let ptrs_ptr = ptrs.as_mut_ptr();
-    let throw_ptr = ptrs_ptr as *mut _;
+    let throw_ptr = ptrs.as_mut_ptr() as *mut _;
 
     // This... may seems surprising, and justifiably so. On 32-bit MSVC the
     // pointers between these structure are just that, pointers. On 64-bit MSVC,
@@ -243,6 +282,12 @@
     //
     // In any case, we basically need to do something like this until we can
     // express more operations in statics (and we may never be able to).
+    if !cfg!(bootstrap) {
+        atomic_store(
+            &mut THROW_INFO.pmfnUnwind as *mut _ as *mut u32,
+            ptr!(exception_cleanup) as u32,
+        );
+    }
     atomic_store(
         &mut THROW_INFO.pCatchableTypeArray as *mut _ as *mut u32,
         ptr!(&CATCHABLE_TYPE_ARRAY as *const _) as u32,
@@ -255,6 +300,12 @@
         &mut CATCHABLE_TYPE.pType as *mut _ as *mut u32,
         ptr!(&TYPE_DESCRIPTOR as *const _) as u32,
     );
+    if !cfg!(bootstrap) {
+        atomic_store(
+            &mut CATCHABLE_TYPE.copyFunction as *mut _ as *mut u32,
+            ptr!(exception_copy) as u32,
+        );
+    }
 
     extern "system" {
         #[unwind(allowed)]
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 0b74a10..c51db69 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -21,7 +21,6 @@
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(allow_internal_unstable)]
-#![feature(const_fn)]
 #![feature(decl_macro)]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs
index 04cd2ef..8adcff6 100644
--- a/src/libprofiler_builtins/build.rs
+++ b/src/libprofiler_builtins/build.rs
@@ -21,7 +21,6 @@
         "InstrProfilingPlatformLinux.c",
         "InstrProfilingPlatformOther.c",
         "InstrProfilingPlatformWindows.c",
-        "InstrProfilingRuntime.cc",
         "InstrProfilingUtil.c",
         "InstrProfilingValue.c",
         "InstrProfilingWriter.c",
@@ -68,10 +67,17 @@
     let root = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
     let root = Path::new(&root);
 
+    let src_root = root.join("lib").join("profile");
     for src in profile_sources {
-        cfg.file(root.join("lib").join("profile").join(src));
+        cfg.file(src_root.join(src));
     }
 
+    // The file was renamed in LLVM 10.
+    let old_runtime_path = src_root.join("InstrProfilingRuntime.cc");
+    let new_runtime_path = src_root.join("InstrProfilingRuntime.cpp");
+    cfg.file(if old_runtime_path.exists() { old_runtime_path } else { new_runtime_path });
+
+    cfg.include(root.join("include"));
     cfg.warnings(false);
     cfg.compile("profiler-rt");
 }
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 2e882cf..b65635b 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -15,7 +15,6 @@
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
-num_cpus = "1.0"
 scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 rustc-rayon = "0.3.0"
@@ -27,8 +26,8 @@
 rustc_target = { path = "../librustc_target" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_index = { path = "../librustc_index" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
@@ -36,8 +35,6 @@
 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 = "1.0", features = ["union", "may_dangle"] }
-measureme = "0.5"
-rustc_error_codes = { path = "../librustc_error_codes" }
+measureme = "0.7.1"
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index cb3fdff..15e92d8 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -123,6 +123,9 @@
             [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
             [] upvars: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
 
+            // Interned types
+            [] tys: rustc::ty::TyS<$tcx>,
+
             // HIR types
             [few] hir_forest: rustc::hir::map::Forest<$tcx>,
             [] arm: rustc_hir::Arm<$tcx>,
@@ -176,7 +179,7 @@
     ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
         #[derive(Default)]
         pub struct Arena<$tcx> {
-            dropless: DroplessArena,
+            pub dropless: DroplessArena,
             drop: DropArena,
             $($name: arena_for_type!($a[$ty]),)*
         }
diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs
index ffb12f1..de82b26 100644
--- a/src/librustc/benches/lib.rs
+++ b/src/librustc/benches/lib.rs
@@ -1,4 +1,4 @@
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(test)]
 
 extern crate test;
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 858627a..9df8e28 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -52,7 +52,7 @@
 use crate::hir::map::DefPathHash;
 use crate::ich::{Fingerprint, StableHashingContext};
 use crate::mir;
-use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{GlobalId, LitToConstInput};
 use crate::traits;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 0d03c83..8d1efc7 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -1,17 +1,18 @@
 use crate::ty::{self, TyCtxt};
-use errors::Diagnostic;
 use parking_lot::{Condvar, Mutex};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::profiling::QueryInvocationId;
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
+use rustc_errors::Diagnostic;
 use rustc_index::vec::{Idx, IndexVec};
 use smallvec::SmallVec;
 use std::collections::hash_map::Entry;
 use std::env;
 use std::hash::Hash;
 use std::mem;
-use std::sync::atomic::Ordering::SeqCst;
+use std::sync::atomic::Ordering::Relaxed;
 
 use crate::ich::{Fingerprint, StableHashingContext, StableHashingContextProvider};
 
@@ -25,6 +26,12 @@
 #[derive(Clone)]
 pub struct DepGraph {
     data: Option<Lrc<DepGraphData>>,
+
+    /// This field is used for assigning DepNodeIndices when running in
+    /// non-incremental mode. Even in non-incremental mode we make sure that
+    /// each task has a `DepNodeIndex` that uniquely identifies it. This unique
+    /// ID is used for self-profiling.
+    virtual_dep_node_index: Lrc<AtomicU32>,
 }
 
 rustc_index::newtype_index! {
@@ -35,6 +42,13 @@
     pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
 }
 
+impl std::convert::From<DepNodeIndex> for QueryInvocationId {
+    #[inline]
+    fn from(dep_node_index: DepNodeIndex) -> Self {
+        QueryInvocationId(dep_node_index.as_u32())
+    }
+}
+
 #[derive(PartialEq)]
 pub enum DepNodeColor {
     Red,
@@ -105,11 +119,12 @@
                 previous: prev_graph,
                 colors: DepNodeColorMap::new(prev_graph_node_count),
             })),
+            virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
         }
     }
 
     pub fn new_disabled() -> DepGraph {
-        DepGraph { data: None }
+        DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
     }
 
     /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
@@ -322,7 +337,7 @@
 
             (result, dep_node_index)
         } else {
-            (task(cx, arg), DepNodeIndex::INVALID)
+            (task(cx, arg), self.next_virtual_depnode_index())
         }
     }
 
@@ -352,7 +367,7 @@
             let dep_node_index = data.current.complete_anon_task(dep_kind, task_deps);
             (result, dep_node_index)
         } else {
-            (op(), DepNodeIndex::INVALID)
+            (op(), self.next_virtual_depnode_index())
         }
     }
 
@@ -478,8 +493,8 @@
             let current_dep_graph = &self.data.as_ref().unwrap().current;
 
             Some((
-                current_dep_graph.total_read_count.load(SeqCst),
-                current_dep_graph.total_duplicate_read_count.load(SeqCst),
+                current_dep_graph.total_read_count.load(Relaxed),
+                current_dep_graph.total_duplicate_read_count.load(Relaxed),
             ))
         } else {
             None
@@ -877,6 +892,11 @@
             }
         }
     }
+
+    fn next_virtual_depnode_index(&self) -> DepNodeIndex {
+        let index = self.virtual_dep_node_index.fetch_add(1, Relaxed);
+        DepNodeIndex::from_u32(index)
+    }
 }
 
 /// A "work product" is an intermediate result that we save into the
@@ -1087,7 +1107,7 @@
             if let Some(task_deps) = icx.task_deps {
                 let mut task_deps = task_deps.lock();
                 if cfg!(debug_assertions) {
-                    self.current.total_read_count.fetch_add(1, SeqCst);
+                    self.current.total_read_count.fetch_add(1, Relaxed);
                 }
                 if task_deps.read_set.insert(source) {
                     task_deps.reads.push(source);
@@ -1105,7 +1125,7 @@
                         }
                     }
                 } else if cfg!(debug_assertions) {
-                    self.current.total_duplicate_read_count.fetch_add(1, SeqCst);
+                    self.current.total_duplicate_read_count.fetch_add(1, Relaxed);
                 }
             }
         })
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 7395b03..86eab3d 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -4,15 +4,17 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use crate::lint::builtin::UNUSED_ATTRIBUTES;
+use crate::hir::map::Map;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
-use rustc_error_codes::*;
+
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::DUMMY_HIR_ID;
 use rustc_hir::{self, HirId, Item, ItemKind, TraitItem, TraitItemKind};
+use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast::Attribute;
@@ -109,7 +111,7 @@
             ItemKind::Union(..) => Target::Union,
             ItemKind::Trait(..) => Target::Trait,
             ItemKind::TraitAlias(..) => Target::TraitAlias,
-            ItemKind::Impl(..) => Target::Impl,
+            ItemKind::Impl { .. } => Target::Impl,
         }
     }
 
@@ -141,7 +143,7 @@
                 let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
                 let containing_item = tcx.hir().expect_item(parent_hir_id);
                 let containing_impl_is_for_trait = match &containing_item.kind {
-                    hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(),
+                    hir::ItemKind::Impl { ref of_trait, .. } => of_trait.is_some(),
                     _ => bug!("parent of an ImplItem must be an Impl"),
                 };
                 if containing_impl_is_for_trait {
@@ -430,21 +432,27 @@
         // Error on repr(transparent, <anything else>).
         if is_transparent && hints.len() > 1 {
             let hint_spans: Vec<_> = hint_spans.clone().collect();
-            span_err!(
+            struct_span_err!(
                 self.tcx.sess,
                 hint_spans,
                 E0692,
                 "transparent {} cannot have other repr hints",
                 target
-            );
+            )
+            .emit();
         }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
             || (is_simd && is_c)
             || (int_reprs == 1 && is_c && item.map_or(false, |item| is_c_like_enum(item)))
         {
-            let hint_spans: Vec<_> = hint_spans.collect();
-            span_warn!(self.tcx.sess, hint_spans, E0566, "conflicting representation hints");
+            struct_span_err!(
+                self.tcx.sess,
+                hint_spans.collect::<Vec<Span>>(),
+                E0566,
+                "conflicting representation hints",
+            )
+            .emit();
         }
     }
 
@@ -511,7 +519,9 @@
 }
 
 impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 2cd4477..016fc93 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -11,9 +11,9 @@
 //! nested within a uniquely determined `FnLike`), and users can ask
 //! for the `Code` associated with a particular NodeId.
 
-use crate::hir::intravisit::FnKind;
-use crate::hir::map;
-use rustc_hir as ast;
+use crate::hir::map::Map;
+use rustc_hir as hir;
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Expr, FnDecl, Node};
 use rustc_span::Span;
 use syntax::ast::{Attribute, Ident};
@@ -39,37 +39,37 @@
     fn is_fn_like(&self) -> bool;
 }
 
-impl MaybeFnLike for ast::Item<'_> {
+impl MaybeFnLike for hir::Item<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::ItemKind::Fn(..) => true,
+            hir::ItemKind::Fn(..) => true,
             _ => false,
         }
     }
 }
 
-impl MaybeFnLike for ast::ImplItem<'_> {
+impl MaybeFnLike for hir::ImplItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::ImplItemKind::Method(..) => true,
+            hir::ImplItemKind::Method(..) => true,
             _ => false,
         }
     }
 }
 
-impl MaybeFnLike for ast::TraitItem<'_> {
+impl MaybeFnLike for hir::TraitItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
             _ => false,
         }
     }
 }
 
-impl MaybeFnLike for ast::Expr<'_> {
+impl MaybeFnLike for hir::Expr<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            ast::ExprKind::Closure(..) => true,
+            hir::ExprKind::Closure(..) => true,
             _ => false,
         }
     }
@@ -85,7 +85,7 @@
 }
 
 impl<'a> Code<'a> {
-    pub fn id(&self) -> ast::HirId {
+    pub fn id(&self) -> hir::HirId {
         match *self {
             Code::FnLike(node) => node.id(),
             Code::Expr(block) => block.hir_id,
@@ -93,13 +93,13 @@
     }
 
     /// Attempts to construct a Code from presumed FnLike or Expr node input.
-    pub fn from_node(map: &map::Map<'a>, id: ast::HirId) -> Option<Code<'a>> {
+    pub fn from_node(map: &Map<'a>, id: hir::HirId) -> Option<Code<'a>> {
         match map.get(id) {
-            map::Node::Block(_) => {
+            Node::Block(_) => {
                 //  Use the parent, hopefully an expression node.
                 Code::from_node(map, map.get_parent_node(id))
             }
-            map::Node::Expr(expr) => Some(Code::Expr(expr)),
+            Node::Expr(expr) => Some(Code::Expr(expr)),
             node => FnLikeNode::from_node(node).map(Code::FnLike),
         }
     }
@@ -109,12 +109,12 @@
 /// use when implementing FnLikeNode operations.
 struct ItemFnParts<'a> {
     ident: Ident,
-    decl: &'a ast::FnDecl<'a>,
-    header: ast::FnHeader,
-    vis: &'a ast::Visibility<'a>,
-    generics: &'a ast::Generics<'a>,
-    body: ast::BodyId,
-    id: ast::HirId,
+    decl: &'a hir::FnDecl<'a>,
+    header: hir::FnHeader,
+    vis: &'a hir::Visibility<'a>,
+    generics: &'a hir::Generics<'a>,
+    body: hir::BodyId,
+    id: hir::HirId,
     span: Span,
     attrs: &'a [Attribute],
 }
@@ -123,8 +123,8 @@
 /// for use when implementing FnLikeNode operations.
 struct ClosureParts<'a> {
     decl: &'a FnDecl<'a>,
-    body: ast::BodyId,
-    id: ast::HirId,
+    body: hir::BodyId,
+    id: hir::HirId,
     span: Span,
     attrs: &'a [Attribute],
 }
@@ -132,8 +132,8 @@
 impl<'a> ClosureParts<'a> {
     fn new(
         d: &'a FnDecl<'a>,
-        b: ast::BodyId,
-        id: ast::HirId,
+        b: hir::BodyId,
+        id: hir::HirId,
         s: Span,
         attrs: &'a [Attribute],
     ) -> Self {
@@ -145,19 +145,19 @@
     /// Attempts to construct a FnLikeNode from presumed FnLike node input.
     pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
         let fn_like = match node {
-            map::Node::Item(item) => item.is_fn_like(),
-            map::Node::TraitItem(tm) => tm.is_fn_like(),
-            map::Node::ImplItem(it) => it.is_fn_like(),
-            map::Node::Expr(e) => e.is_fn_like(),
+            Node::Item(item) => item.is_fn_like(),
+            Node::TraitItem(tm) => tm.is_fn_like(),
+            Node::ImplItem(it) => it.is_fn_like(),
+            Node::Expr(e) => e.is_fn_like(),
             _ => false,
         };
         fn_like.then_some(FnLikeNode { node })
     }
 
-    pub fn body(self) -> ast::BodyId {
+    pub fn body(self) -> hir::BodyId {
         self.handle(
             |i: ItemFnParts<'a>| i.body,
-            |_, _, _: &'a ast::FnSig<'a>, _, body: ast::BodyId, _, _| body,
+            |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _, _| body,
             |c: ClosureParts<'a>| c.body,
         )
     }
@@ -165,7 +165,7 @@
     pub fn decl(self) -> &'a FnDecl<'a> {
         self.handle(
             |i: ItemFnParts<'a>| &*i.decl,
-            |_, _, sig: &'a ast::FnSig<'a>, _, _, _, _| &sig.decl,
+            |_, _, sig: &'a hir::FnSig<'a>, _, _, _, _| &sig.decl,
             |c: ClosureParts<'a>| c.decl,
         )
     }
@@ -173,29 +173,29 @@
     pub fn span(self) -> Span {
         self.handle(
             |i: ItemFnParts<'_>| i.span,
-            |_, _, _: &'a ast::FnSig<'a>, _, _, span, _| span,
+            |_, _, _: &'a hir::FnSig<'a>, _, _, span, _| span,
             |c: ClosureParts<'_>| c.span,
         )
     }
 
-    pub fn id(self) -> ast::HirId {
+    pub fn id(self) -> hir::HirId {
         self.handle(
             |i: ItemFnParts<'_>| i.id,
-            |id, _, _: &'a ast::FnSig<'a>, _, _, _, _| id,
+            |id, _, _: &'a hir::FnSig<'a>, _, _, _, _| id,
             |c: ClosureParts<'_>| c.id,
         )
     }
 
-    pub fn constness(self) -> ast::Constness {
-        self.kind().header().map_or(ast::Constness::NotConst, |header| header.constness)
+    pub fn constness(self) -> hir::Constness {
+        self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness)
     }
 
-    pub fn asyncness(self) -> ast::IsAsync {
-        self.kind().header().map_or(ast::IsAsync::NotAsync, |header| header.asyncness)
+    pub fn asyncness(self) -> hir::IsAsync {
+        self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness)
     }
 
-    pub fn unsafety(self) -> ast::Unsafety {
-        self.kind().header().map_or(ast::Unsafety::Normal, |header| header.unsafety)
+    pub fn unsafety(self) -> hir::Unsafety {
+        self.kind().header().map_or(hir::Unsafety::Normal, |header| header.unsafety)
     }
 
     pub fn kind(self) -> FnKind<'a> {
@@ -203,7 +203,7 @@
             FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs)
         };
         let closure = |c: ClosureParts<'a>| FnKind::Closure(c.attrs);
-        let method = |_, ident: Ident, sig: &'a ast::FnSig<'a>, vis, _, _, attrs| {
+        let method = |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _, attrs| {
             FnKind::Method(ident, sig, vis, attrs)
         };
         self.handle(item, method, closure)
@@ -213,19 +213,19 @@
     where
         I: FnOnce(ItemFnParts<'a>) -> A,
         M: FnOnce(
-            ast::HirId,
+            hir::HirId,
             Ident,
-            &'a ast::FnSig<'a>,
-            Option<&'a ast::Visibility<'a>>,
-            ast::BodyId,
+            &'a hir::FnSig<'a>,
+            Option<&'a hir::Visibility<'a>>,
+            hir::BodyId,
             Span,
             &'a [Attribute],
         ) -> A,
         C: FnOnce(ClosureParts<'a>) -> A,
     {
         match self.node {
-            map::Node::Item(i) => match i.kind {
-                ast::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
+            Node::Item(i) => match i.kind {
+                hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
                     id: i.hir_id,
                     ident: i.ident,
                     decl: &sig.decl,
@@ -238,20 +238,20 @@
                 }),
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
-            map::Node::TraitItem(ti) => match ti.kind {
-                ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
+            Node::TraitItem(ti) => match ti.kind {
+                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
                     method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
-            map::Node::ImplItem(ii) => match ii.kind {
-                ast::ImplItemKind::Method(ref sig, body) => {
+            Node::ImplItem(ii) => match ii.kind {
+                hir::ImplItemKind::Method(ref sig, body) => {
                     method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                 }
                 _ => bug!("impl method FnLikeNode that is not fn-like"),
             },
-            map::Node::Expr(e) => match e.kind {
-                ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
+            Node::Expr(e) => match e.kind {
+                hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
                     closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs))
                 }
                 _ => bug!("expr FnLikeNode that is not fn-like"),
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 6879e8f..b6be4bb 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -1,22 +1,24 @@
-use super::*;
-use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex};
-use crate::hir::intravisit::{NestedVisitorMap, Visitor};
-use crate::hir::map::HirEntryMap;
-use crate::ich::Fingerprint;
+use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
+use crate::hir::map::definitions::{self, DefPathHash};
+use crate::hir::map::{Entry, HirEntryMap, Map};
+use crate::ich::StableHashingContext;
 use crate::middle::cstore::CrateStore;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
+use rustc_hir::def_id::CRATE_DEF_INDEX;
 use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::*;
 use rustc_index::vec::IndexVec;
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::SourceMap;
-use rustc_span::Span;
-use std::iter::repeat;
+use rustc_span::{Span, Symbol, DUMMY_SP};
 use syntax::ast::NodeId;
 
-use crate::ich::StableHashingContext;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use std::iter::repeat;
 
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
@@ -49,15 +51,12 @@
     hir_body_nodes: Vec<(DefPathHash, Fingerprint)>,
 }
 
-fn input_dep_node_and_hash<I>(
+fn input_dep_node_and_hash(
     dep_graph: &DepGraph,
     hcx: &mut StableHashingContext<'_>,
     dep_node: DepNode,
-    input: I,
-) -> (DepNodeIndex, Fingerprint)
-where
-    I: for<'a> HashStable<StableHashingContext<'a>>,
-{
+    input: impl for<'a> HashStable<StableHashingContext<'a>>,
+) -> (DepNodeIndex, Fingerprint) {
     let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1;
 
     let hash = if dep_graph.is_fully_enabled() {
@@ -71,16 +70,13 @@
     (dep_node_index, hash)
 }
 
-fn alloc_hir_dep_nodes<I>(
+fn alloc_hir_dep_nodes(
     dep_graph: &DepGraph,
     hcx: &mut StableHashingContext<'_>,
     def_path_hash: DefPathHash,
-    item_like: I,
+    item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
     hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
-) -> (DepNodeIndex, DepNodeIndex)
-where
-    I: for<'a> HashStable<StableHashingContext<'a>>,
-{
+) -> (DepNodeIndex, DepNodeIndex) {
     let sig = dep_graph
         .input_task(
             def_path_hash.to_dep_node(DepKind::Hir),
@@ -98,6 +94,21 @@
     (sig, full)
 }
 
+fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
+    let mut upstream_crates: Vec<_> = cstore
+        .crates_untracked()
+        .iter()
+        .map(|&cnum| {
+            let name = cstore.crate_name_untracked(cnum);
+            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
+            let hash = cstore.crate_hash_untracked(cnum);
+            (name, disambiguator, hash)
+        })
+        .collect();
+    upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
+    upstream_crates
+}
+
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(
         sess: &'a Session,
@@ -190,18 +201,7 @@
             },
         );
 
-        let mut upstream_crates: Vec<_> = cstore
-            .crates_untracked()
-            .iter()
-            .map(|&cnum| {
-                let name = cstore.crate_name_untracked(cnum);
-                let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
-                let hash = cstore.crate_hash_untracked(cnum);
-                (name, disambiguator, hash)
-            })
-            .collect();
-
-        upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
+        let upstream_crates = upstream_crates(cstore);
 
         // We hash the final, remapped names of all local source files so we
         // don't have to include the path prefix remapping commandline args.
@@ -336,11 +336,13 @@
 }
 
 impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
+    type Map = Map<'hir>;
+
     /// Because we want to track parent items and so forth, enable
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         panic!("`visit_nested_xxx` must be manually implemented in this visitor");
     }
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 67d29b3..ac2d7a9 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -4,7 +4,7 @@
 //! There are also some rather random cases (like const initializer
 //! expressions) that are mostly just leftovers.
 
-use crate::ich::Fingerprint;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_hir as hir;
@@ -15,10 +15,11 @@
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use syntax::ast;
+
 use std::borrow::Borrow;
 use std::fmt::Write;
 use std::hash::Hash;
-use syntax::ast;
 
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index 6329970..76e42b8 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -1,9 +1,9 @@
-use crate::hir::intravisit;
 use crate::hir::map::Map;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ItemLocalId};
 
@@ -133,7 +133,9 @@
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'hir> {
+    type Map = Map<'hir>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 0a165ac..6d7f531 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -4,13 +4,13 @@
 };
 
 use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
-use crate::hir::intravisit;
 use crate::middle::cstore::CrateStoreDyn;
 use crate::ty::query::Providers;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::Nested;
 use rustc_hir::*;
@@ -18,7 +18,7 @@
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::kw;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, Name, NodeId};
 
@@ -186,12 +186,12 @@
 }
 
 impl<'map, 'hir> ParentHirIterator<'map, 'hir> {
-    fn new(current_id: HirId, map: &'map Map<'hir>) -> ParentHirIterator<'map, 'hir> {
-        ParentHirIterator { current_id, map }
+    fn new(current_id: HirId, map: &'map Map<'hir>) -> Self {
+        Self { current_id, map }
     }
 }
 
-impl<'map, 'hir> Iterator for ParentHirIterator<'map, 'hir> {
+impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
     type Item = (HirId, Node<'hir>);
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -341,7 +341,7 @@
                 | ItemKind::Use(..)
                 | ItemKind::ForeignMod(..)
                 | ItemKind::GlobalAsm(..)
-                | ItemKind::Impl(..) => return None,
+                | ItemKind::Impl { .. } => return None,
             },
             Node::ForeignItem(item) => match item.kind {
                 ForeignItemKind::Fn(..) => DefKind::Fn,
@@ -405,6 +405,14 @@
         self.forest.krate()
     }
 
+    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.read(id);
+
+        // N.B., intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.item(id)
+    }
+
     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
         self.read(id.hir_id);
 
@@ -596,7 +604,7 @@
                 | ItemKind::Union(_, ref generics)
                 | ItemKind::Trait(_, _, ref generics, ..)
                 | ItemKind::TraitAlias(ref generics, _)
-                | ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics),
+                | ItemKind::Impl { ref generics, .. } => Some(generics),
                 _ => None,
             },
             _ => None,
@@ -813,7 +821,7 @@
                     | ItemKind::Struct(..)
                     | ItemKind::Union(..)
                     | ItemKind::Trait(..)
-                    | ItemKind::Impl(..) => true,
+                    | ItemKind::Impl { .. } => true,
                     _ => false,
                 },
                 Node::ForeignItem(fi) => match fi.kind {
@@ -1085,6 +1093,24 @@
     }
 }
 
+impl<'hir> intravisit::Map<'hir> for Map<'hir> {
+    fn body(&self, id: BodyId) -> &'hir Body<'hir> {
+        self.body(id)
+    }
+
+    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.item(id)
+    }
+
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        self.trait_item(id)
+    }
+
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.impl_item(id)
+    }
+}
+
 pub struct NodesMatchingSuffix<'a> {
     map: &'a Map<'a>,
     item_name: &'a String,
@@ -1244,7 +1270,7 @@
         definitions,
     };
 
-    sess.time("validate HIR map", || {
+    sess.time("validate_HIR_map", || {
         hir_id_validator::check_crate(&map);
     });
 
@@ -1306,7 +1332,7 @@
                 ItemKind::Union(..) => "union",
                 ItemKind::Trait(..) => "trait",
                 ItemKind::TraitAlias(..) => "trait alias",
-                ItemKind::Impl(..) => "impl",
+                ItemKind::Impl { .. } => "impl",
             };
             format!("{} {}{}", item_str, path_str(), id_str)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 3087fc3..97c14dd 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -4,7 +4,6 @@
 
 pub mod check_attr;
 pub mod exports;
-pub mod intravisit;
 pub mod map;
 pub mod upvars;
 
diff --git a/src/librustc/hir/upvars.rs b/src/librustc/hir/upvars.rs
index df02a79..4ca294f 100644
--- a/src/librustc/hir/upvars.rs
+++ b/src/librustc/hir/upvars.rs
@@ -1,11 +1,12 @@
 //! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.
 
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use crate::hir::map::Map;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{self, HirId};
 use rustc_span::Span;
 
@@ -43,7 +44,9 @@
 }
 
 impl Visitor<'tcx> for LocalCollector {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -70,7 +73,9 @@
 }
 
 impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 5e402dc..012900f 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -22,7 +22,7 @@
 use crate::ty::fold::TypeFoldable;
 use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, BoundVar, Ty, TyCtxt};
-use crate::util::captures::Captures;
+use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 use rustc_index::vec::IndexVec;
 use rustc_span::DUMMY_SP;
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index f262672..77182b9 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -64,13 +64,13 @@
     subst::{Subst, SubstsRef},
     Region, Ty, TyCtxt, TypeFoldable,
 };
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
-
-use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
-use rustc_error_codes::*;
-use rustc_span::{Pos, Span};
+use rustc_span::{DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::{cmp, fmt};
 
@@ -253,7 +253,7 @@
 
 fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
     match item.kind {
-        hir::ItemKind::Impl(..) => "impl",
+        hir::ItemKind::Impl { .. } => "impl",
         hir::ItemKind::Struct(..) => "struct",
         hir::ItemKind::Union(..) => "union",
         hir::ItemKind::Enum(..) => "enum",
@@ -1289,6 +1289,8 @@
         mut values: Option<ValuePairs<'tcx>>,
         terr: &TypeError<'tcx>,
     ) {
+        let span = cause.span(self.tcx);
+
         // For some types of errors, expected-found does not make
         // sense, so just ignore the values we were given.
         match terr {
@@ -1298,6 +1300,100 @@
             _ => {}
         }
 
+        struct OpaqueTypesVisitor<'tcx> {
+            types: FxHashMap<TyCategory, FxHashSet<Span>>,
+            expected: FxHashMap<TyCategory, FxHashSet<Span>>,
+            found: FxHashMap<TyCategory, FxHashSet<Span>>,
+            ignore_span: Span,
+            tcx: TyCtxt<'tcx>,
+        }
+
+        impl<'tcx> OpaqueTypesVisitor<'tcx> {
+            fn visit_expected_found(
+                tcx: TyCtxt<'tcx>,
+                expected: Ty<'tcx>,
+                found: Ty<'tcx>,
+                ignore_span: Span,
+            ) -> Self {
+                let mut types_visitor = OpaqueTypesVisitor {
+                    types: Default::default(),
+                    expected: Default::default(),
+                    found: Default::default(),
+                    ignore_span,
+                    tcx,
+                };
+                // The visitor puts all the relevant encountered types in `self.types`, but in
+                // here we want to visit two separate types with no relation to each other, so we
+                // move the results from `types` to `expected` or `found` as appropriate.
+                expected.visit_with(&mut types_visitor);
+                std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
+                found.visit_with(&mut types_visitor);
+                std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
+                types_visitor
+            }
+
+            fn report(&self, err: &mut DiagnosticBuilder<'_>) {
+                self.add_labels_for_types(err, "expected", &self.expected);
+                self.add_labels_for_types(err, "found", &self.found);
+            }
+
+            fn add_labels_for_types(
+                &self,
+                err: &mut DiagnosticBuilder<'_>,
+                target: &str,
+                types: &FxHashMap<TyCategory, FxHashSet<Span>>,
+            ) {
+                for (key, values) in types.iter() {
+                    let count = values.len();
+                    let kind = key.descr();
+                    for sp in values {
+                        err.span_label(
+                            *sp,
+                            format!(
+                                "{}{}{} {}{}",
+                                if sp.is_desugaring(DesugaringKind::Async) {
+                                    "the `Output` of this `async fn`'s "
+                                } else if count == 1 {
+                                    "the "
+                                } else {
+                                    ""
+                                },
+                                if count > 1 { "one of the " } else { "" },
+                                target,
+                                kind,
+                                pluralize!(count),
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                if let Some((kind, def_id)) = TyCategory::from_ty(t) {
+                    let span = self.tcx.def_span(def_id);
+                    // Avoid cluttering the output when the "found" and error span overlap:
+                    //
+                    // error[E0308]: mismatched types
+                    //   --> $DIR/issue-20862.rs:2:5
+                    //    |
+                    // LL |     |y| x + y
+                    //    |     ^^^^^^^^^
+                    //    |     |
+                    //    |     the found closure
+                    //    |     expected `()`, found closure
+                    //    |
+                    //    = note: expected unit type `()`
+                    //                 found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
+                    if !self.ignore_span.overlaps(span) {
+                        self.types.entry(kind).or_default().insert(span);
+                    }
+                }
+                t.super_visit_with(self)
+            }
+        }
+
         debug!("note_type_err(diag={:?})", diag);
         let (expected_found, exp_found, is_simple_error) = match values {
             None => (None, None, false),
@@ -1306,6 +1402,13 @@
                     ValuePairs::Types(exp_found) => {
                         let is_simple_err =
                             exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
+                        OpaqueTypesVisitor::visit_expected_found(
+                            self.tcx,
+                            exp_found.expected,
+                            exp_found.found,
+                            span,
+                        )
+                        .report(diag);
 
                         (is_simple_err, Some(exp_found))
                     }
@@ -1323,8 +1426,6 @@
             }
         };
 
-        let span = cause.span(self.tcx);
-
         // Ignore msg for object safe coercion
         // since E0038 message will be printed
         match terr {
@@ -1336,7 +1437,6 @@
                 }
             }
         };
-
         if let Some((expected, found)) = expected_found {
             let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string());
             let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string());
@@ -1907,7 +2007,7 @@
                 TypeError::IntrinsicCast => {
                     Error0308("cannot coerce intrinsics to function pointers")
                 }
-                TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()),
+                TypeError::ObjectUnsafeCoercion(did) => Error0038(*did),
                 _ => Error0308("mismatched types"),
             },
         }
@@ -1933,3 +2033,34 @@
         }
     }
 }
+
+/// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
+/// extra information about each type, but we only care about the category.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+crate enum TyCategory {
+    Closure,
+    Opaque,
+    Generator,
+    Foreign,
+}
+
+impl TyCategory {
+    fn descr(&self) -> &'static str {
+        match self {
+            Self::Closure => "closure",
+            Self::Opaque => "opaque type",
+            Self::Generator => "generator",
+            Self::Foreign => "foreign type",
+        }
+    }
+
+    pub fn from_ty(ty: Ty<'_>) -> Option<(Self, DefId)> {
+        match ty.kind {
+            ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
+            ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
+            ty::Generator(def_id, ..) => Some((Self::Generator, def_id)),
+            ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
+            _ => None,
+        }
+    }
+}
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 091bfba..9947dea 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -1,20 +1,18 @@
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use crate::hir::map::Map;
 use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::infer::InferCtxt;
 use crate::ty::print::Print;
 use crate::ty::{self, DefIdTree, Infer, Ty, TyVar};
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FunctionRetTy, HirId, Local, Pat};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
 use std::borrow::Cow;
 
-use rustc_error_codes::*;
-
 struct FindLocalByTypeVisitor<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     target_ty: Ty<'tcx>,
@@ -66,7 +64,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.hir_map)
     }
 
@@ -149,16 +149,13 @@
     E0284,
 }
 
-impl Into<errors::DiagnosticId> for TypeAnnotationNeeded {
-    fn into(self) -> errors::DiagnosticId {
-        syntax::diagnostic_used!(E0282);
-        syntax::diagnostic_used!(E0283);
-        syntax::diagnostic_used!(E0284);
-        errors::DiagnosticId::Error(match self {
-            Self::E0282 => "E0282".to_string(),
-            Self::E0283 => "E0283".to_string(),
-            Self::E0284 => "E0284".to_string(),
-        })
+impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
+    fn into(self) -> rustc_errors::DiagnosticId {
+        match self {
+            Self::E0282 => rustc_errors::error_code!(E0282),
+            Self::E0283 => rustc_errors::error_code!(E0283),
+            Self::E0284 => rustc_errors::error_code!(E0284),
+        }
     }
 }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index cfb6d5b..8f4c643 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -5,7 +5,7 @@
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::util::common::ErrorReported;
 
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when both the concerned regions are anonymous.
diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
index 6edf8f1..8e2592b 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -1,8 +1,9 @@
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use crate::hir::map::Map;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::middle::resolve_lifetime as rl;
 use crate::ty::{self, Region, TyCtxt};
 use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::Node;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
@@ -90,7 +91,9 @@
 }
 
 impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -207,7 +210,9 @@
 }
 
 impl Visitor<'tcx> for TyPathVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'tcx>> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
index 5da65a3..8749d6c 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
@@ -3,7 +3,7 @@
 use crate::infer::InferCtxt;
 use crate::ty::{self, TyCtxt};
 use crate::util::common::ErrorReported;
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_span::source_map::Span;
 
 mod different_lifetimes;
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 0d56fc5..df37f53 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -2,11 +2,9 @@
 //! where one region is named and the other is anonymous.
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::ty;
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir::{FunctionRetTy, TyKind};
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// When given a `ConcreteFailure` for a function with parameters containing a named region and
     /// an anonymous region, emit an descriptive diagnostic error.
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 f276dab..7b31fe7 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
@@ -7,7 +7,7 @@
 use crate::ty::print::{FmtPrinter, Print, RegionHighlightMode};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, TyCtxt};
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 6c78e70..c6fc4cd 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -5,7 +5,7 @@
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::ty::{BoundRegion, FreeRegion, RegionKind};
 use crate::util::common::ErrorReported;
-use errors::Applicability;
+use rustc_errors::Applicability;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index 7919274..11dda71 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -3,9 +3,7 @@
 use crate::middle::region;
 use crate::ty::error::TypeError;
 use crate::ty::{self, Region};
-use errors::DiagnosticBuilder;
-
-use rustc_error_codes::*;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub(super) fn note_region_origin(
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index e78382c..18c25ef 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -19,7 +19,6 @@
     Direction, Graph, NodeIndex, INCOMING, OUTGOING,
 };
 use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::Span;
 use std::fmt;
@@ -204,9 +203,7 @@
         // want to stop at the first constraint that makes a change.
         let mut any_changed = false;
         for member_constraint in &self.data.member_constraints {
-            if self.enforce_member_constraint(graph, member_constraint, var_values) {
-                any_changed = true;
-            }
+            any_changed |= self.enforce_member_constraint(graph, member_constraint, var_values);
         }
         any_changed
     }
@@ -297,64 +294,59 @@
     }
 
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
-        let mut process_constraint = |constraint: &Constraint<'tcx>| {
-            let (a_region, b_vid, b_data, retain) = match *constraint {
+        let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
+        let mut changes = Vec::new();
+        for constraint in self.data.constraints.keys() {
+            let (a_vid, a_region, b_vid, b_data) = match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    (a_region, b_vid, b_data, false)
+                    (None, a_region, b_vid, b_data)
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
-                    VarValue::ErrorValue => return (false, false),
+                    VarValue::ErrorValue => continue,
                     VarValue::Value(a_region) => {
                         let b_data = var_values.value_mut(b_vid);
-                        let retain = match *b_data {
-                            VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
-                            _ => true,
-                        };
-                        (a_region, b_vid, b_data, retain)
+                        (Some(a_vid), a_region, b_vid, b_data)
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    return (false, false);
+                    continue;
                 }
             };
-
-            let changed = self.expand_node(a_region, b_vid, b_data);
-            (changed, retain)
-        };
-
-        // Using bitsets to track the remaining elements is faster than using a
-        // `Vec` by itself (which requires removing elements, which requires
-        // element shuffling, which is slow).
-        let constraints: Vec<_> = self.data.constraints.keys().collect();
-        let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
-        let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
-        let mut changed = true;
-        while changed {
-            changed = false;
-            for index in live_indices.iter() {
-                let constraint = constraints[index];
-                let (edge_changed, retain) = process_constraint(constraint);
-                if edge_changed {
-                    changed = true;
-                }
-                if !retain {
-                    let changed = killed_indices.insert(index);
-                    debug_assert!(changed);
+            if self.expand_node(a_region, b_vid, b_data) {
+                changes.push(b_vid);
+            }
+            if let Some(a_vid) = a_vid {
+                match *b_data {
+                    VarValue::Value(ReStatic) | VarValue::ErrorValue => (),
+                    _ => {
+                        constraints[a_vid].push((a_vid, b_vid));
+                        constraints[b_vid].push((a_vid, b_vid));
+                    }
                 }
             }
-            live_indices.subtract(&killed_indices);
+        }
 
-            // We could clear `killed_indices` here, but we don't need to and
-            // it's cheaper not to.
+        while let Some(vid) = changes.pop() {
+            constraints[vid].retain(|&(a_vid, b_vid)| {
+                let a_region = match *var_values.value(a_vid) {
+                    VarValue::ErrorValue => return false,
+                    VarValue::Value(a_region) => a_region,
+                };
+                let b_data = var_values.value_mut(b_vid);
+                if self.expand_node(a_region, b_vid, b_data) {
+                    changes.push(b_vid);
+                }
+                match *b_data {
+                    VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
+                    _ => true,
+                }
+            });
         }
     }
 
-    // This function is very hot in some workloads. There's a single callsite
-    // so always inlining is ok even though it's large.
-    #[inline(always)]
     fn expand_node(
         &self,
         a_region: Region<'tcx>,
@@ -794,8 +786,8 @@
             self.var_infos[node_idx].origin.span(),
             &format!(
                 "collect_error_for_expanding_node() could not find \
-                      error for var {:?} in universe {:?}, lower_bounds={:#?}, \
-                      upper_bounds={:#?}",
+                 error for var {:?} in universe {:?}, lower_bounds={:#?}, \
+                 upper_bounds={:#?}",
                 node_idx, node_universe, lower_bounds, upper_bounds
             ),
         );
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 4eb8d79..f67669e 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -21,10 +21,10 @@
 use crate::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
 use crate::ty::{ConstVid, FloatVid, IntVid, TyVid};
 
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unify as ut;
+use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::Symbol;
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index a22ed94..fe3a5d1 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -6,17 +6,15 @@
 use crate::ty::free_region_map::FreeRegionRelations;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use errors::DiagnosticBuilder;
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_hir::Node;
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
 
 /// Information about the opaque types whose values we
@@ -524,11 +522,7 @@
         err.span_label(span, label);
 
         if nightly_options::is_nightly_build() {
-            help!(
-                err,
-                "add #![feature(member_constraints)] to the crate attributes \
-                   to enable"
-            );
+            err.help("add #![feature(member_constraints)] to the crate attributes to enable");
         }
 
         err.emit();
@@ -1223,7 +1217,7 @@
     let res = hir_id == scope;
     trace!(
         "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
-        tcx.hir().get(hir_id),
+        tcx.hir().find(hir_id),
         tcx.hir().get(opaque_hir_id),
         res
     );
diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs
index 0380d0e..8ee8482 100644
--- a/src/librustc/infer/outlives/verify.rs
+++ b/src/librustc/infer/outlives/verify.rs
@@ -3,7 +3,7 @@
 use crate::traits;
 use crate::ty::subst::{InternalSubsts, Subst};
 use crate::ty::{self, Ty, TyCtxt};
-use crate::util::captures::Captures;
+use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 
 /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 37761c1..69ca406 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -31,11 +31,9 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(const_transmute)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
-#![cfg_attr(windows, feature(libc))]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(overlapping_marker_traits)]
@@ -44,12 +42,13 @@
 #![feature(optin_builtin_traits)]
 #![feature(option_expect_none)]
 #![feature(range_is_empty)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(thread_local)]
 #![feature(trace_macros)]
 #![feature(trusted_len)]
+#![feature(vec_remove_item)]
 #![feature(stmt_expr_attributes)]
 #![feature(integer_atomics)]
 #![feature(test)]
@@ -72,8 +71,6 @@
 #[macro_use]
 extern crate log;
 #[macro_use]
-extern crate syntax;
-#[macro_use]
 extern crate smallvec;
 
 #[cfg(test)]
@@ -100,7 +97,6 @@
 
 pub mod util {
     pub mod bug;
-    pub mod captures;
     pub mod common;
 }
 
diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs
new file mode 100644
index 0000000..2ed6cd5
--- /dev/null
+++ b/src/librustc/lint.rs
@@ -0,0 +1,369 @@
+use std::cmp;
+
+use crate::ich::StableHashingContext;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_hir::HirId;
+pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass};
+use rustc_session::{DiagnosticMessageId, Session};
+use rustc_span::hygiene::MacroKind;
+use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
+use rustc_span::{Span, Symbol};
+
+/// How a lint level was set.
+#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
+pub enum LintSource {
+    /// Lint is at the default level as declared
+    /// in rustc or a plugin.
+    Default,
+
+    /// Lint level was set by an attribute.
+    Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */),
+
+    /// Lint level was set by a command-line flag.
+    CommandLine(Symbol),
+}
+
+pub type LevelSource = (Level, LintSource);
+
+pub struct LintLevelSets {
+    pub list: Vec<LintSet>,
+    pub lint_cap: Level,
+}
+
+pub enum LintSet {
+    CommandLine {
+        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+        // flag.
+        specs: FxHashMap<LintId, LevelSource>,
+    },
+
+    Node {
+        specs: FxHashMap<LintId, LevelSource>,
+        parent: u32,
+    },
+}
+
+impl LintLevelSets {
+    pub fn new() -> Self {
+        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+    }
+
+    pub fn get_lint_level(
+        &self,
+        lint: &'static Lint,
+        idx: u32,
+        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        sess: &Session,
+    ) -> LevelSource {
+        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
+
+        // If `level` is none then we actually assume the default level for this
+        // lint.
+        let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
+
+        // If we're about to issue a warning, check at the last minute for any
+        // directives against the warnings "lint". If, for example, there's an
+        // `allow(warnings)` in scope then we want to respect that instead.
+        if level == Level::Warn {
+            let (warnings_level, warnings_src) =
+                self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux);
+            if let Some(configured_warning_level) = warnings_level {
+                if configured_warning_level != Level::Warn {
+                    level = configured_warning_level;
+                    src = warnings_src;
+                }
+            }
+        }
+
+        // Ensure that we never exceed the `--cap-lints` argument.
+        level = cmp::min(level, self.lint_cap);
+
+        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
+            // Ensure that we never exceed driver level.
+            level = cmp::min(*driver_level, level);
+        }
+
+        return (level, src);
+    }
+
+    pub fn get_lint_id_level(
+        &self,
+        id: LintId,
+        mut idx: u32,
+        aux: Option<&FxHashMap<LintId, LevelSource>>,
+    ) -> (Option<Level>, LintSource) {
+        if let Some(specs) = aux {
+            if let Some(&(level, src)) = specs.get(&id) {
+                return (Some(level), src);
+            }
+        }
+        loop {
+            match self.list[idx as usize] {
+                LintSet::CommandLine { ref specs } => {
+                    if let Some(&(level, src)) = specs.get(&id) {
+                        return (Some(level), src);
+                    }
+                    return (None, LintSource::Default);
+                }
+                LintSet::Node { ref specs, parent } => {
+                    if let Some(&(level, src)) = specs.get(&id) {
+                        return (Some(level), src);
+                    }
+                    idx = parent;
+                }
+            }
+        }
+    }
+}
+
+pub struct LintLevelMap {
+    pub sets: LintLevelSets,
+    pub id_to_set: FxHashMap<HirId, u32>,
+}
+
+impl LintLevelMap {
+    /// If the `id` was previously registered with `register_id` when building
+    /// this `LintLevelMap` this returns the corresponding lint level and source
+    /// of the lint level for the lint provided.
+    ///
+    /// If the `id` was not previously registered, returns `None`. If `None` is
+    /// returned then the parent of `id` should be acquired and this function
+    /// should be called again.
+    pub fn level_and_source(
+        &self,
+        lint: &'static Lint,
+        id: HirId,
+        session: &Session,
+    ) -> Option<LevelSource> {
+        self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        let LintLevelMap { ref sets, ref id_to_set } = *self;
+
+        id_to_set.hash_stable(hcx, hasher);
+
+        let LintLevelSets { ref list, lint_cap } = *sets;
+
+        lint_cap.hash_stable(hcx, hasher);
+
+        hcx.while_hashing_spans(true, |hcx| {
+            list.len().hash_stable(hcx, hasher);
+
+            // We are working under the assumption here that the list of
+            // lint-sets is built in a deterministic order.
+            for lint_set in list {
+                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
+
+                match *lint_set {
+                    LintSet::CommandLine { ref specs } => {
+                        specs.hash_stable(hcx, hasher);
+                    }
+                    LintSet::Node { ref specs, parent } => {
+                        specs.hash_stable(hcx, hasher);
+                        parent.hash_stable(hcx, hasher);
+                    }
+                }
+            }
+        })
+    }
+}
+
+pub fn struct_lint_level<'a>(
+    sess: &'a Session,
+    lint: &'static Lint,
+    level: Level,
+    src: LintSource,
+    span: Option<MultiSpan>,
+    msg: &str,
+) -> DiagnosticBuilder<'a> {
+    let mut err = match (level, span) {
+        (Level::Allow, _) => return sess.diagnostic().struct_dummy(),
+        (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg),
+        (Level::Warn, None) => sess.struct_warn(msg),
+        (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg),
+        (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg),
+    };
+
+    // Check for future incompatibility lints and issue a stronger warning.
+    let lint_id = LintId::of(lint);
+    let future_incompatible = lint.future_incompatible;
+
+    // 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 => {
+            sess.diag_note_once(
+                &mut err,
+                DiagnosticMessageId::from(lint),
+                &format!("`#[{}({})]` on by default", level.as_str(), name),
+            );
+        }
+        LintSource::CommandLine(lint_flag_val) => {
+            let flag = match level {
+                Level::Warn => "-W",
+                Level::Deny => "-D",
+                Level::Forbid => "-F",
+                Level::Allow => panic!(),
+            };
+            let hyphen_case_lint_name = name.replace("_", "-");
+            if lint_flag_val.as_str() == name {
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    &format!(
+                        "requested on the command line with `{} {}`",
+                        flag, hyphen_case_lint_name
+                    ),
+                );
+            } else {
+                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    &format!(
+                        "`{} {}` implied by `{} {}`",
+                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
+                    ),
+                );
+            }
+        }
+        LintSource::Node(lint_attr_name, src, reason) => {
+            if let Some(rationale) = reason {
+                err.note(&rationale.as_str());
+            }
+            sess.diag_span_note_once(
+                &mut err,
+                DiagnosticMessageId::from(lint),
+                src,
+                "lint level defined here",
+            );
+            if lint_attr_name.as_str() != name {
+                let level_str = level.as_str();
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    &format!(
+                        "`#[{}({})]` implied by `#[{}({})]`",
+                        level_str, name, level_str, lint_attr_name
+                    ),
+                );
+            }
+        }
+    }
+
+    err.code(DiagnosticId::Lint(name));
+
+    if let Some(future_incompatible) = future_incompatible {
+        const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
+             it will become a hard error";
+
+        let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
+            "once this method is added to the standard library, \
+             the ambiguity may cause an error or change in behavior!"
+                .to_owned()
+        } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
+            "this borrowing pattern was not meant to be accepted, \
+             and may become a hard error in the future"
+                .to_owned()
+        } else if let Some(edition) = future_incompatible.edition {
+            format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
+        } else {
+            format!("{} in a future release!", STANDARD_MESSAGE)
+        };
+        let citation = format!("for more information, see {}", future_incompatible.reference);
+        err.warn(&explanation);
+        err.note(&citation);
+    }
+
+    return err;
+}
+
+/// Returns whether `span` originates in a foreign crate's external macro.
+///
+/// This is used to test whether a lint should not even begin to figure out whether it should
+/// be reported on the current node.
+pub fn in_external_macro(sess: &Session, span: Span) -> bool {
+    let expn_data = span.ctxt().outer_expn_data();
+    match expn_data.kind {
+        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
+        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.
+                return true;
+            }
+            match sess.source_map().span_to_snippet(expn_data.def_site) {
+                Ok(code) => !code.starts_with("macro_rules"),
+                // No snippet means external macro or compiler-builtin expansion.
+                Err(_) => true,
+            }
+        }
+        ExpnKind::Macro(..) => true, // definitely a plugin
+    }
+}
+
+pub fn add_elided_lifetime_in_path_suggestion(
+    sess: &Session,
+    db: &mut DiagnosticBuilder<'_>,
+    n: usize,
+    path_span: Span,
+    incl_angl_brckt: bool,
+    insertion_span: Span,
+    anon_lts: String,
+) {
+    let (replace_span, suggestion) = if incl_angl_brckt {
+        (insertion_span, anon_lts)
+    } else {
+        // When possible, prefer a suggestion that replaces the whole
+        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
+        // at a point (which makes for an ugly/confusing label)
+        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
+            // But our spans can get out of whack due to macros; if the place we think
+            // we want to insert `'_` isn't even within the path expression's span, we
+            // should bail out of making any suggestion rather than panicking on a
+            // subtract-with-overflow or string-slice-out-out-bounds (!)
+            // FIXME: can we do better?
+            if insertion_span.lo().0 < path_span.lo().0 {
+                return;
+            }
+            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
+            if insertion_index > snippet.len() {
+                return;
+            }
+            let (before, after) = snippet.split_at(insertion_index);
+            (path_span, format!("{}{}{}", before, anon_lts, after))
+        } else {
+            (insertion_span, anon_lts)
+        }
+    };
+    db.span_suggestion(
+        replace_span,
+        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
+        suggestion,
+        Applicability::MachineApplicable,
+    );
+}
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
deleted file mode 100644
index 78d01ff..0000000
--- a/src/librustc/lint/levels.rs
+++ /dev/null
@@ -1,549 +0,0 @@
-use std::cmp;
-
-use crate::ich::StableHashingContext;
-use crate::lint::builtin;
-use crate::lint::context::{CheckLintNameResult, LintStore};
-use crate::lint::{self, Level, Lint, LintId, LintSource};
-use crate::session::Session;
-use errors::{Applicability, DiagnosticBuilder};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::HirId;
-use rustc_span::source_map::MultiSpan;
-use rustc_span::symbol::{sym, Symbol};
-use syntax::ast;
-use syntax::attr;
-use syntax::feature_gate;
-use syntax::print::pprust;
-
-use rustc_error_codes::*;
-
-pub struct LintLevelSets {
-    list: Vec<LintSet>,
-    lint_cap: Level,
-}
-
-enum LintSet {
-    CommandLine {
-        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
-        // flag.
-        specs: FxHashMap<LintId, (Level, LintSource)>,
-    },
-
-    Node {
-        specs: FxHashMap<LintId, (Level, LintSource)>,
-        parent: u32,
-    },
-}
-
-impl LintLevelSets {
-    pub fn new(sess: &Session, lint_store: &LintStore) -> LintLevelSets {
-        let mut me = LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid };
-        me.process_command_line(sess, lint_store);
-        return me;
-    }
-
-    pub fn builder<'a>(
-        sess: &'a Session,
-        warn_about_weird_lints: bool,
-        store: &LintStore,
-    ) -> LintLevelsBuilder<'a> {
-        LintLevelsBuilder::new(sess, warn_about_weird_lints, LintLevelSets::new(sess, store))
-    }
-
-    fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
-        let mut specs = FxHashMap::default();
-        self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
-
-        for &(ref lint_name, level) in &sess.opts.lint_opts {
-            store.check_lint_name_cmdline(sess, &lint_name, level);
-
-            // If the cap is less than this specified level, e.g., if we've got
-            // `--cap-lints allow` but we've also got `-D foo` then we ignore
-            // this specification as the lint cap will set it to allow anyway.
-            let level = cmp::min(level, self.lint_cap);
-
-            let lint_flag_val = Symbol::intern(lint_name);
-            let ids = match store.find_lints(&lint_name) {
-                Ok(ids) => ids,
-                Err(_) => continue, // errors handled in check_lint_name_cmdline above
-            };
-            for id in ids {
-                let src = LintSource::CommandLine(lint_flag_val);
-                specs.insert(id, (level, src));
-            }
-        }
-
-        self.list.push(LintSet::CommandLine { specs: specs });
-    }
-
-    fn get_lint_level(
-        &self,
-        lint: &'static Lint,
-        idx: u32,
-        aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
-        sess: &Session,
-    ) -> (Level, LintSource) {
-        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
-
-        // If `level` is none then we actually assume the default level for this
-        // lint.
-        let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
-
-        // If we're about to issue a warning, check at the last minute for any
-        // directives against the warnings "lint". If, for example, there's an
-        // `allow(warnings)` in scope then we want to respect that instead.
-        if level == Level::Warn {
-            let (warnings_level, warnings_src) =
-                self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), idx, aux);
-            if let Some(configured_warning_level) = warnings_level {
-                if configured_warning_level != Level::Warn {
-                    level = configured_warning_level;
-                    src = warnings_src;
-                }
-            }
-        }
-
-        // Ensure that we never exceed the `--cap-lints` argument.
-        level = cmp::min(level, self.lint_cap);
-
-        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
-            // Ensure that we never exceed driver level.
-            level = cmp::min(*driver_level, level);
-        }
-
-        return (level, src);
-    }
-
-    fn get_lint_id_level(
-        &self,
-        id: LintId,
-        mut idx: u32,
-        aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
-    ) -> (Option<Level>, LintSource) {
-        if let Some(specs) = aux {
-            if let Some(&(level, src)) = specs.get(&id) {
-                return (Some(level), src);
-            }
-        }
-        loop {
-            match self.list[idx as usize] {
-                LintSet::CommandLine { ref specs } => {
-                    if let Some(&(level, src)) = specs.get(&id) {
-                        return (Some(level), src);
-                    }
-                    return (None, LintSource::Default);
-                }
-                LintSet::Node { ref specs, parent } => {
-                    if let Some(&(level, src)) = specs.get(&id) {
-                        return (Some(level), src);
-                    }
-                    idx = parent;
-                }
-            }
-        }
-    }
-}
-
-pub struct LintLevelsBuilder<'a> {
-    sess: &'a Session,
-    sets: LintLevelSets,
-    id_to_set: FxHashMap<HirId, u32>,
-    cur: u32,
-    warn_about_weird_lints: bool,
-}
-
-pub struct BuilderPush {
-    prev: u32,
-    pub changed: bool,
-}
-
-impl<'a> LintLevelsBuilder<'a> {
-    pub fn new(
-        sess: &'a Session,
-        warn_about_weird_lints: bool,
-        sets: LintLevelSets,
-    ) -> LintLevelsBuilder<'a> {
-        assert_eq!(sets.list.len(), 1);
-        LintLevelsBuilder {
-            sess,
-            sets,
-            cur: 0,
-            id_to_set: Default::default(),
-            warn_about_weird_lints,
-        }
-    }
-
-    /// Pushes a list of AST lint attributes onto this context.
-    ///
-    /// This function will return a `BuilderPush` object which should be passed
-    /// to `pop` when this scope for the attributes provided is exited.
-    ///
-    /// This function will perform a number of tasks:
-    ///
-    /// * It'll validate all lint-related attributes in `attrs`
-    /// * It'll mark all lint-related attributes as used
-    /// * Lint levels will be updated based on the attributes provided
-    /// * Lint attributes are validated, e.g., a #[forbid] can't be switched to
-    ///   #[allow]
-    ///
-    /// Don't forget to call `pop`!
-    pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush {
-        let mut specs = FxHashMap::default();
-        let sess = self.sess;
-        let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
-        for attr in attrs {
-            let level = match Level::from_symbol(attr.name_or_empty()) {
-                None => continue,
-                Some(lvl) => lvl,
-            };
-
-            let meta = unwrap_or!(attr.meta(), continue);
-            attr::mark_used(attr);
-
-            let mut metas = unwrap_or!(meta.meta_item_list(), continue);
-
-            if metas.is_empty() {
-                // FIXME (#55112): issue unused-attributes lint for `#[level()]`
-                continue;
-            }
-
-            // Before processing the lint names, look for a reason (RFC 2383)
-            // at the end.
-            let mut reason = None;
-            let tail_li = &metas[metas.len() - 1];
-            if let Some(item) = tail_li.meta_item() {
-                match item.kind {
-                    ast::MetaItemKind::Word => {} // actual lint names handled later
-                    ast::MetaItemKind::NameValue(ref name_value) => {
-                        if item.path == sym::reason {
-                            // found reason, reslice meta list to exclude it
-                            metas = &metas[0..metas.len() - 1];
-                            // FIXME (#55112): issue unused-attributes lint if we thereby
-                            // don't have any lint names (`#[level(reason = "foo")]`)
-                            if let ast::LitKind::Str(rationale, _) = name_value.kind {
-                                if !self.sess.features_untracked().lint_reasons {
-                                    feature_gate::feature_err(
-                                        &self.sess.parse_sess,
-                                        sym::lint_reasons,
-                                        item.span,
-                                        "lint reasons are experimental",
-                                    )
-                                    .emit();
-                                }
-                                reason = Some(rationale);
-                            } else {
-                                bad_attr(name_value.span)
-                                    .span_label(name_value.span, "reason must be a string literal")
-                                    .emit();
-                            }
-                        } else {
-                            bad_attr(item.span)
-                                .span_label(item.span, "bad attribute argument")
-                                .emit();
-                        }
-                    }
-                    ast::MetaItemKind::List(_) => {
-                        bad_attr(item.span).span_label(item.span, "bad attribute argument").emit();
-                    }
-                }
-            }
-
-            for li in metas {
-                let meta_item = match li.meta_item() {
-                    Some(meta_item) if meta_item.is_word() => meta_item,
-                    _ => {
-                        let sp = li.span();
-                        let mut err = bad_attr(sp);
-                        let mut add_label = true;
-                        if let Some(item) = li.meta_item() {
-                            if let ast::MetaItemKind::NameValue(_) = item.kind {
-                                if item.path == sym::reason {
-                                    err.span_label(sp, "reason in lint attribute must come last");
-                                    add_label = false;
-                                }
-                            }
-                        }
-                        if add_label {
-                            err.span_label(sp, "bad attribute argument");
-                        }
-                        err.emit();
-                        continue;
-                    }
-                };
-                let tool_name = if meta_item.path.segments.len() > 1 {
-                    let tool_ident = meta_item.path.segments[0].ident;
-                    if !attr::is_known_lint_tool(tool_ident) {
-                        span_err!(
-                            sess,
-                            tool_ident.span,
-                            E0710,
-                            "an unknown tool name found in scoped lint: `{}`",
-                            pprust::path_to_string(&meta_item.path),
-                        );
-                        continue;
-                    }
-
-                    Some(tool_ident.name)
-                } else {
-                    None
-                };
-                let name = meta_item.path.segments.last().expect("empty lint name").ident.name;
-                match store.check_lint_name(&name.as_str(), tool_name) {
-                    CheckLintNameResult::Ok(ids) => {
-                        let src = LintSource::Node(name, li.span(), reason);
-                        for id in ids {
-                            specs.insert(*id, (level, src));
-                        }
-                    }
-
-                    CheckLintNameResult::Tool(result) => {
-                        match result {
-                            Ok(ids) => {
-                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
-                                let src = LintSource::Node(
-                                    Symbol::intern(complete_name),
-                                    li.span(),
-                                    reason,
-                                );
-                                for id in ids {
-                                    specs.insert(*id, (level, src));
-                                }
-                            }
-                            Err((Some(ids), new_lint_name)) => {
-                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
-                                let (lvl, src) =
-                                    self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
-                                let msg = format!(
-                                    "lint name `{}` is deprecated \
-                                     and may not have an effect in the future. \
-                                     Also `cfg_attr(cargo-clippy)` won't be necessary anymore",
-                                    name
-                                );
-                                lint::struct_lint_level(
-                                    self.sess,
-                                    lint,
-                                    lvl,
-                                    src,
-                                    Some(li.span().into()),
-                                    &msg,
-                                )
-                                .span_suggestion(
-                                    li.span(),
-                                    "change it to",
-                                    new_lint_name.to_string(),
-                                    Applicability::MachineApplicable,
-                                )
-                                .emit();
-
-                                let src = LintSource::Node(
-                                    Symbol::intern(&new_lint_name),
-                                    li.span(),
-                                    reason,
-                                );
-                                for id in ids {
-                                    specs.insert(*id, (level, src));
-                                }
-                            }
-                            Err((None, _)) => {
-                                // If Tool(Err(None, _)) is returned, then either the lint does not
-                                // exist in the tool or the code was not compiled with the tool and
-                                // therefore the lint was never added to the `LintStore`. To detect
-                                // this is the responsibility of the lint tool.
-                            }
-                        }
-                    }
-
-                    _ if !self.warn_about_weird_lints => {}
-
-                    CheckLintNameResult::Warning(msg, renamed) => {
-                        let lint = builtin::RENAMED_AND_REMOVED_LINTS;
-                        let (level, src) =
-                            self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
-                        let mut err = lint::struct_lint_level(
-                            self.sess,
-                            lint,
-                            level,
-                            src,
-                            Some(li.span().into()),
-                            &msg,
-                        );
-                        if let Some(new_name) = renamed {
-                            err.span_suggestion(
-                                li.span(),
-                                "use the new name",
-                                new_name,
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                        err.emit();
-                    }
-                    CheckLintNameResult::NoLint(suggestion) => {
-                        let lint = builtin::UNKNOWN_LINTS;
-                        let (level, src) =
-                            self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
-                        let msg = format!("unknown lint: `{}`", name);
-                        let mut db = lint::struct_lint_level(
-                            self.sess,
-                            lint,
-                            level,
-                            src,
-                            Some(li.span().into()),
-                            &msg,
-                        );
-
-                        if let Some(suggestion) = suggestion {
-                            db.span_suggestion(
-                                li.span(),
-                                "did you mean",
-                                suggestion.to_string(),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-
-                        db.emit();
-                    }
-                }
-            }
-        }
-
-        for (id, &(level, ref src)) in specs.iter() {
-            if level == Level::Forbid {
-                continue;
-            }
-            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) {
-                (Some(Level::Forbid), src) => src,
-                _ => continue,
-            };
-            let forbidden_lint_name = match forbid_src {
-                LintSource::Default => id.to_string(),
-                LintSource::Node(name, _, _) => name.to_string(),
-                LintSource::CommandLine(name) => name.to_string(),
-            };
-            let (lint_attr_name, lint_attr_span) = match *src {
-                LintSource::Node(name, span, _) => (name, span),
-                _ => continue,
-            };
-            let mut diag_builder = struct_span_err!(
-                self.sess,
-                lint_attr_span,
-                E0453,
-                "{}({}) overruled by outer forbid({})",
-                level.as_str(),
-                lint_attr_name,
-                forbidden_lint_name
-            );
-            diag_builder.span_label(lint_attr_span, "overruled by previous forbid");
-            match forbid_src {
-                LintSource::Default => {}
-                LintSource::Node(_, forbid_source_span, reason) => {
-                    diag_builder.span_label(forbid_source_span, "`forbid` level set here");
-                    if let Some(rationale) = reason {
-                        diag_builder.note(&rationale.as_str());
-                    }
-                }
-                LintSource::CommandLine(_) => {
-                    diag_builder.note("`forbid` lint level was set on command line");
-                }
-            }
-            diag_builder.emit();
-            // don't set a separate error for every lint in the group
-            break;
-        }
-
-        let prev = self.cur;
-        if specs.len() > 0 {
-            self.cur = self.sets.list.len() as u32;
-            self.sets.list.push(LintSet::Node { specs: specs, parent: prev });
-        }
-
-        BuilderPush { prev: prev, changed: prev != self.cur }
-    }
-
-    /// Called after `push` when the scope of a set of attributes are exited.
-    pub fn pop(&mut self, push: BuilderPush) {
-        self.cur = push.prev;
-    }
-
-    /// Used to emit a lint-related diagnostic based on the current state of
-    /// this lint context.
-    pub fn struct_lint(
-        &self,
-        lint: &'static Lint,
-        span: Option<MultiSpan>,
-        msg: &str,
-    ) -> DiagnosticBuilder<'a> {
-        let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess);
-        lint::struct_lint_level(self.sess, lint, level, src, span, msg)
-    }
-
-    /// Registers the ID provided with the current set of lints stored in
-    /// this context.
-    pub fn register_id(&mut self, id: HirId) {
-        self.id_to_set.insert(id, self.cur);
-    }
-
-    pub fn build(self) -> LintLevelSets {
-        self.sets
-    }
-
-    pub fn build_map(self) -> LintLevelMap {
-        LintLevelMap { sets: self.sets, id_to_set: self.id_to_set }
-    }
-}
-
-pub struct LintLevelMap {
-    sets: LintLevelSets,
-    id_to_set: FxHashMap<HirId, u32>,
-}
-
-impl LintLevelMap {
-    /// If the `id` was previously registered with `register_id` when building
-    /// this `LintLevelMap` this returns the corresponding lint level and source
-    /// of the lint level for the lint provided.
-    ///
-    /// If the `id` was not previously registered, returns `None`. If `None` is
-    /// returned then the parent of `id` should be acquired and this function
-    /// should be called again.
-    pub fn level_and_source(
-        &self,
-        lint: &'static Lint,
-        id: HirId,
-        session: &Session,
-    ) -> Option<(Level, LintSource)> {
-        self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set } = *self;
-
-        id_to_set.hash_stable(hcx, hasher);
-
-        let LintLevelSets { ref list, lint_cap } = *sets;
-
-        lint_cap.hash_stable(hcx, hasher);
-
-        hcx.while_hashing_spans(true, |hcx| {
-            list.len().hash_stable(hcx, hasher);
-
-            // We are working under the assumption here that the list of
-            // lint-sets is built in a deterministic order.
-            for lint_set in list {
-                ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
-
-                match *lint_set {
-                    LintSet::CommandLine { ref specs } => {
-                        specs.hash_stable(hcx, hasher);
-                    }
-                    LintSet::Node { ref specs, parent } => {
-                        specs.hash_stable(hcx, hasher);
-                        parent.hash_stable(hcx, hasher);
-                    }
-                }
-            }
-        })
-    }
-}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
deleted file mode 100644
index 2147ff1..0000000
--- a/src/librustc/lint/mod.rs
+++ /dev/null
@@ -1,593 +0,0 @@
-//! Lints, aka compiler warnings.
-//!
-//! A 'lint' check is a kind of miscellaneous constraint that a user _might_
-//! want to enforce, but might reasonably want to permit as well, on a
-//! module-by-module basis. They contrast with static constraints enforced by
-//! other phases of the compiler, which are generally required to hold in order
-//! to compile the program at all.
-//!
-//! Most lints can be written as `LintPass` instances. These run after
-//! all other analyses. The `LintPass`es built into rustc are defined
-//! within `builtin.rs`, which has further comments on how to add such a lint.
-//! rustc can also load user-defined lint plugins via the plugin mechanism.
-//!
-//! Some of rustc's lints are defined elsewhere in the compiler and work by
-//! calling `add_lint()` on the overall `Session` object. This works when
-//! it happens before the main lint pass, which emits the lints stored by
-//! `add_lint()`. To emit lints after the main lint pass (from codegen, for
-//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
-//! in `context.rs`.
-
-pub use self::Level::*;
-pub use self::LintSource::*;
-
-use rustc_data_structures::sync;
-
-use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::ty::TyCtxt;
-use errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_hir as hir;
-use rustc_session::node_id::NodeMap;
-use rustc_session::{DiagnosticMessageId, Session};
-use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-use syntax::ast;
-
-pub use crate::lint::context::{
-    BufferedEarlyLint, CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore,
-};
-
-pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
-
-/// Declares a static `LintArray` and return it as an expression.
-#[macro_export]
-macro_rules! lint_array {
-    ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
-    ($( $lint:expr ),*) => {{
-        vec![$($lint),*]
-    }}
-}
-
-pub type LintArray = Vec<&'static Lint>;
-
-pub trait LintPass {
-    fn name(&self) -> &'static str;
-}
-
-/// Implements `LintPass for $name` with the given list of `Lint` statics.
-#[macro_export]
-macro_rules! impl_lint_pass {
-    ($name:ident => [$($lint:expr),* $(,)?]) => {
-        impl LintPass for $name {
-            fn name(&self) -> &'static str { stringify!($name) }
-        }
-        impl $name {
-            pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) }
-        }
-    };
-}
-
-/// Declares a type named `$name` which implements `LintPass`.
-/// To the right of `=>` a comma separated list of `Lint` statics is given.
-#[macro_export]
-macro_rules! declare_lint_pass {
-    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
-        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
-        $crate::impl_lint_pass!($name => [$($lint),*]);
-    };
-}
-
-#[macro_export]
-macro_rules! late_lint_methods {
-    ($macro:path, $args:tt, [$hir:tt]) => (
-        $macro!($args, [$hir], [
-            fn check_param(a: &$hir hir::Param<$hir>);
-            fn check_body(a: &$hir hir::Body<$hir>);
-            fn check_body_post(a: &$hir hir::Body<$hir>);
-            fn check_name(a: Span, b: ast::Name);
-            fn check_crate(a: &$hir hir::Crate<$hir>);
-            fn check_crate_post(a: &$hir hir::Crate<$hir>);
-            fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
-            fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
-            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
-            fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
-            fn check_item(a: &$hir hir::Item<$hir>);
-            fn check_item_post(a: &$hir hir::Item<$hir>);
-            fn check_local(a: &$hir hir::Local<$hir>);
-            fn check_block(a: &$hir hir::Block<$hir>);
-            fn check_block_post(a: &$hir hir::Block<$hir>);
-            fn check_stmt(a: &$hir hir::Stmt<$hir>);
-            fn check_arm(a: &$hir hir::Arm<$hir>);
-            fn check_pat(a: &$hir hir::Pat<$hir>);
-            fn check_expr(a: &$hir hir::Expr<$hir>);
-            fn check_expr_post(a: &$hir hir::Expr<$hir>);
-            fn check_ty(a: &$hir hir::Ty<$hir>);
-            fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
-            fn check_generics(a: &$hir hir::Generics<$hir>);
-            fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
-            fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
-            fn check_fn(
-                a: $crate::hir::intravisit::FnKind<$hir>,
-                b: &$hir hir::FnDecl<$hir>,
-                c: &$hir hir::Body<$hir>,
-                d: Span,
-                e: hir::HirId);
-            fn check_fn_post(
-                a: $crate::hir::intravisit::FnKind<$hir>,
-                b: &$hir hir::FnDecl<$hir>,
-                c: &$hir hir::Body<$hir>,
-                d: Span,
-                e: hir::HirId
-            );
-            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
-            fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
-            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
-            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
-            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
-            fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
-            fn check_struct_field(a: &$hir hir::StructField<$hir>);
-            fn check_variant(a: &$hir hir::Variant<$hir>);
-            fn check_variant_post(a: &$hir hir::Variant<$hir>);
-            fn check_lifetime(a: &$hir hir::Lifetime);
-            fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
-            fn check_attribute(a: &$hir ast::Attribute);
-
-            /// Called when entering a syntax node that can have lint attributes such
-            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-            fn enter_lint_attrs(a: &$hir [ast::Attribute]);
-
-            /// Counterpart to `enter_lint_attrs`.
-            fn exit_lint_attrs(a: &$hir [ast::Attribute]);
-        ]);
-    )
-}
-
-/// Trait for types providing lint checks.
-///
-/// Each `check` method checks a single syntax node, and should not
-/// invoke methods recursively (unlike `Visitor`). By default they
-/// do nothing.
-//
-// FIXME: eliminate the duplication with `Visitor`. But this also
-// contains a few lint-specific methods with no equivalent in `Visitor`.
-
-macro_rules! expand_lint_pass_methods {
-    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
-    )
-}
-
-macro_rules! declare_late_lint_pass {
-    ([], [$hir:tt], [$($methods:tt)*]) => (
-        pub trait LateLintPass<'a, $hir>: LintPass {
-            expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
-        }
-    )
-}
-
-late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
-
-#[macro_export]
-macro_rules! expand_combined_late_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
-    })
-}
-
-#[macro_export]
-macro_rules! expand_combined_late_lint_pass_methods {
-    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) {
-            expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
-        })*
-    )
-}
-
-#[macro_export]
-macro_rules! declare_combined_late_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
-        #[allow(non_snake_case)]
-        $v struct $name {
-            $($passes: $passes,)*
-        }
-
-        impl $name {
-            $v fn new() -> Self {
-                Self {
-                    $($passes: $constructor,)*
-                }
-            }
-
-            $v fn get_lints() -> LintArray {
-                let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
-                lints
-            }
-        }
-
-        impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
-            expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
-        }
-
-        impl LintPass for $name {
-            fn name(&self) -> &'static str {
-                panic!()
-            }
-        }
-    )
-}
-
-#[macro_export]
-macro_rules! early_lint_methods {
-    ($macro:path, $args:tt) => (
-        $macro!($args, [
-            fn check_param(a: &ast::Param);
-            fn check_ident(a: ast::Ident);
-            fn check_crate(a: &ast::Crate);
-            fn check_crate_post(a: &ast::Crate);
-            fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId);
-            fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId);
-            fn check_foreign_item(a: &ast::ForeignItem);
-            fn check_foreign_item_post(a: &ast::ForeignItem);
-            fn check_item(a: &ast::Item);
-            fn check_item_post(a: &ast::Item);
-            fn check_local(a: &ast::Local);
-            fn check_block(a: &ast::Block);
-            fn check_block_post(a: &ast::Block);
-            fn check_stmt(a: &ast::Stmt);
-            fn check_arm(a: &ast::Arm);
-            fn check_pat(a: &ast::Pat);
-            fn check_pat_post(a: &ast::Pat);
-            fn check_expr(a: &ast::Expr);
-            fn check_expr_post(a: &ast::Expr);
-            fn check_ty(a: &ast::Ty);
-            fn check_generic_param(a: &ast::GenericParam);
-            fn check_generics(a: &ast::Generics);
-            fn check_where_predicate(a: &ast::WherePredicate);
-            fn check_poly_trait_ref(a: &ast::PolyTraitRef,
-                                    b: &ast::TraitBoundModifier);
-            fn check_fn(a: syntax::visit::FnKind<'_>, b: &ast::FnDecl, c: Span, d_: ast::NodeId);
-            fn check_fn_post(
-                a: syntax::visit::FnKind<'_>,
-                b: &ast::FnDecl,
-                c: Span,
-                d: ast::NodeId
-            );
-            fn check_trait_item(a: &ast::AssocItem);
-            fn check_trait_item_post(a: &ast::AssocItem);
-            fn check_impl_item(a: &ast::AssocItem);
-            fn check_impl_item_post(a: &ast::AssocItem);
-            fn check_struct_def(a: &ast::VariantData);
-            fn check_struct_def_post(a: &ast::VariantData);
-            fn check_struct_field(a: &ast::StructField);
-            fn check_variant(a: &ast::Variant);
-            fn check_variant_post(a: &ast::Variant);
-            fn check_lifetime(a: &ast::Lifetime);
-            fn check_path(a: &ast::Path, b: ast::NodeId);
-            fn check_attribute(a: &ast::Attribute);
-            fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
-            fn check_mac(a: &ast::Mac);
-
-            /// Called when entering a syntax node that can have lint attributes such
-            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-            fn enter_lint_attrs(a: &[ast::Attribute]);
-
-            /// Counterpart to `enter_lint_attrs`.
-            fn exit_lint_attrs(a: &[ast::Attribute]);
-        ]);
-    )
-}
-
-macro_rules! expand_early_lint_pass_methods {
-    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
-    )
-}
-
-macro_rules! declare_early_lint_pass {
-    ([], [$($methods:tt)*]) => (
-        pub trait EarlyLintPass: LintPass {
-            expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
-        }
-    )
-}
-
-early_lint_methods!(declare_early_lint_pass, []);
-
-#[macro_export]
-macro_rules! expand_combined_early_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
-    })
-}
-
-#[macro_export]
-macro_rules! expand_combined_early_lint_pass_methods {
-    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
-            expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
-        })*
-    )
-}
-
-#[macro_export]
-macro_rules! declare_combined_early_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
-        #[allow(non_snake_case)]
-        $v struct $name {
-            $($passes: $passes,)*
-        }
-
-        impl $name {
-            $v fn new() -> Self {
-                Self {
-                    $($passes: $constructor,)*
-                }
-            }
-
-            $v fn get_lints() -> LintArray {
-                let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
-                lints
-            }
-        }
-
-        impl EarlyLintPass for $name {
-            expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
-        }
-
-        impl LintPass for $name {
-            fn name(&self) -> &'static str {
-                panic!()
-            }
-        }
-    )
-}
-
-/// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
-pub type LateLintPassObject =
-    Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>;
-
-/// How a lint level was set.
-#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
-pub enum LintSource {
-    /// Lint is at the default level as declared
-    /// in rustc or a plugin.
-    Default,
-
-    /// Lint level was set by an attribute.
-    Node(ast::Name, Span, Option<Symbol> /* RFC 2383 reason */),
-
-    /// Lint level was set by a command-line flag.
-    CommandLine(Symbol),
-}
-
-pub type LevelSource = (Level, LintSource);
-
-pub mod builtin;
-mod context;
-pub mod internal;
-mod levels;
-
-pub use self::levels::{LintLevelMap, LintLevelSets, LintLevelsBuilder};
-
-#[derive(Default)]
-pub struct LintBuffer {
-    pub map: NodeMap<Vec<BufferedEarlyLint>>,
-}
-
-impl LintBuffer {
-    pub fn add_lint(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: MultiSpan,
-        msg: &str,
-        diagnostic: BuiltinLintDiagnostics,
-    ) {
-        let early_lint = BufferedEarlyLint {
-            lint_id: LintId::of(lint),
-            ast_id: id,
-            span: sp,
-            msg: msg.to_string(),
-            diagnostic,
-        };
-        let arr = self.map.entry(id).or_default();
-        if !arr.contains(&early_lint) {
-            arr.push(early_lint);
-        }
-    }
-
-    pub fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> {
-        self.map.remove(&id).unwrap_or_default()
-    }
-
-    pub fn buffer_lint<S: Into<MultiSpan>>(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: S,
-        msg: &str,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
-    }
-
-    pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
-        &mut self,
-        lint: &'static Lint,
-        id: ast::NodeId,
-        sp: S,
-        msg: &str,
-        diagnostic: BuiltinLintDiagnostics,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, diagnostic)
-    }
-}
-
-pub fn struct_lint_level<'a>(
-    sess: &'a Session,
-    lint: &'static Lint,
-    level: Level,
-    src: LintSource,
-    span: Option<MultiSpan>,
-    msg: &str,
-) -> DiagnosticBuilder<'a> {
-    let mut err = match (level, span) {
-        (Level::Allow, _) => return sess.diagnostic().struct_dummy(),
-        (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg),
-        (Level::Warn, None) => sess.struct_warn(msg),
-        (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg),
-        (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg),
-    };
-
-    // Check for future incompatibility lints and issue a stronger warning.
-    let lint_id = LintId::of(lint);
-    let future_incompatible = lint.future_incompatible;
-
-    // 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 => {
-            sess.diag_note_once(
-                &mut err,
-                DiagnosticMessageId::from(lint),
-                &format!("`#[{}({})]` on by default", level.as_str(), name),
-            );
-        }
-        LintSource::CommandLine(lint_flag_val) => {
-            let flag = match level {
-                Level::Warn => "-W",
-                Level::Deny => "-D",
-                Level::Forbid => "-F",
-                Level::Allow => panic!(),
-            };
-            let hyphen_case_lint_name = name.replace("_", "-");
-            if lint_flag_val.as_str() == name {
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "requested on the command line with `{} {}`",
-                        flag, hyphen_case_lint_name
-                    ),
-                );
-            } else {
-                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`{} {}` implied by `{} {}`",
-                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
-                    ),
-                );
-            }
-        }
-        LintSource::Node(lint_attr_name, src, reason) => {
-            if let Some(rationale) = reason {
-                err.note(&rationale.as_str());
-            }
-            sess.diag_span_note_once(
-                &mut err,
-                DiagnosticMessageId::from(lint),
-                src,
-                "lint level defined here",
-            );
-            if lint_attr_name.as_str() != name {
-                let level_str = level.as_str();
-                sess.diag_note_once(
-                    &mut err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`#[{}({})]` implied by `#[{}({})]`",
-                        level_str, name, level_str, lint_attr_name
-                    ),
-                );
-            }
-        }
-    }
-
-    err.code(DiagnosticId::Lint(name));
-
-    if let Some(future_incompatible) = future_incompatible {
-        const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \
-             it will become a hard error";
-
-        let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
-            "once this method is added to the standard library, \
-             the ambiguity may cause an error or change in behavior!"
-                .to_owned()
-        } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
-            "this borrowing pattern was not meant to be accepted, \
-             and may become a hard error in the future"
-                .to_owned()
-        } else if let Some(edition) = future_incompatible.edition {
-            format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
-        } else {
-            format!("{} in a future release!", STANDARD_MESSAGE)
-        };
-        let citation = format!("for more information, see {}", future_incompatible.reference);
-        err.warn(&explanation);
-        err.note(&citation);
-    }
-
-    return err;
-}
-
-pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
-    let attrs = tcx.hir().attrs(id);
-    attrs.iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some())
-}
-
-/// Returns whether `span` originates in a foreign crate's external macro.
-///
-/// This is used to test whether a lint should not even begin to figure out whether it should
-/// be reported on the current node.
-pub fn in_external_macro(sess: &Session, span: Span) -> bool {
-    let expn_data = span.ctxt().outer_expn_data();
-    match expn_data.kind {
-        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
-        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.
-                return true;
-            }
-            match sess.source_map().span_to_snippet(expn_data.def_site) {
-                Ok(code) => !code.starts_with("macro_rules"),
-                // No snippet means external macro or compiler-builtin expansion.
-                Err(_) => true,
-            }
-        }
-        ExpnKind::Macro(..) => true, // definitely a plugin
-    }
-}
-
-/// 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;
-    }
-    false
-}
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index ee43c35..0e7ff3a 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -5,8 +5,8 @@
 use crate::hir::map as hir_map;
 use crate::hir::map::definitions::{DefKey, DefPathTable};
 use crate::session::search_paths::PathKind;
-use crate::session::{CrateDisambiguator, Session};
-use crate::ty::{self, TyCtxt};
+use crate::session::CrateDisambiguator;
+use crate::ty::TyCtxt;
 
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, MetadataRef};
@@ -27,7 +27,7 @@
 
 /// Where a crate came from on the local filesystem. One of these three options
 /// must be non-None.
-#[derive(PartialEq, Clone, Debug, HashStable)]
+#[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub struct CrateSource {
     pub dylib: Option<(PathBuf, PathKind)>,
     pub rlib: Option<(PathBuf, PathKind)>,
@@ -75,7 +75,7 @@
     }
 }
 
-#[derive(PartialEq, Clone, Debug)]
+#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum LibSource {
     Some(PathBuf),
     MetadataOnly,
@@ -160,6 +160,7 @@
     Path,
 }
 
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct EncodedMetadata {
     pub raw_data: Vec<u8>,
 }
@@ -208,7 +209,6 @@
     fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
-    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
 
     // This is basically a 1-based range of ints, which is a little
     // silly - I may fix that.
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 8b2bf55..6ece51f 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -19,7 +19,7 @@
 /// This is local to the tcx, and is generally relevant to one session.
 pub type Dependencies = Vec<(config::CrateType, DependencyList)>;
 
-#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub enum Linkage {
     NotLinked,
     IncludedFromDylib,
diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs
index e4af54f..1f4318f 100644
--- a/src/librustc/middle/exported_symbols.rs
+++ b/src/librustc/middle/exported_symbols.rs
@@ -1,10 +1,7 @@
-use crate::ich::StableHashingContext;
 use crate::ty::subst::SubstsRef;
-use crate::ty::{self, TyCtxt};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use std::cmp;
-use std::mem;
+use rustc_macros::HashStable;
 
 /// The SymbolExportLevel of a symbols specifies from which kinds of crates
 /// the symbol will be exported. `C` symbols will be exported from any
@@ -24,47 +21,29 @@
     }
 }
 
-#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum ExportedSymbol<'tcx> {
     NonGeneric(DefId),
     Generic(DefId, SubstsRef<'tcx>),
+    DropGlue(Ty<'tcx>),
     NoDefId(ty::SymbolName),
 }
 
 impl<'tcx> ExportedSymbol<'tcx> {
-    pub fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName {
+    /// This is the symbol name of an instance if it is instantiated in the
+    /// local crate.
+    pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName {
         match *self {
             ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
             ExportedSymbol::Generic(def_id, substs) => {
                 tcx.symbol_name(ty::Instance::new(def_id, substs))
             }
+            ExportedSymbol::DropGlue(ty) => {
+                tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
+            }
             ExportedSymbol::NoDefId(symbol_name) => symbol_name,
         }
     }
-
-    pub fn compare_stable(&self, tcx: TyCtxt<'tcx>, other: &ExportedSymbol<'tcx>) -> cmp::Ordering {
-        match *self {
-            ExportedSymbol::NonGeneric(self_def_id) => match *other {
-                ExportedSymbol::NonGeneric(other_def_id) => {
-                    tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
-                }
-                ExportedSymbol::Generic(..) | ExportedSymbol::NoDefId(_) => cmp::Ordering::Less,
-            },
-            ExportedSymbol::Generic(..) => match *other {
-                ExportedSymbol::NonGeneric(_) => cmp::Ordering::Greater,
-                ExportedSymbol::Generic(..) => self.symbol_name(tcx).cmp(&other.symbol_name(tcx)),
-                ExportedSymbol::NoDefId(_) => cmp::Ordering::Less,
-            },
-            ExportedSymbol::NoDefId(self_symbol_name) => match *other {
-                ExportedSymbol::NonGeneric(_) | ExportedSymbol::Generic(..) => {
-                    cmp::Ordering::Greater
-                }
-                ExportedSymbol::NoDefId(ref other_symbol_name) => {
-                    self_symbol_name.cmp(other_symbol_name)
-                }
-            },
-        }
-    }
 }
 
 pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
@@ -74,21 +53,3 @@
         tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
     )
 }
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ExportedSymbol<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            ExportedSymbol::NonGeneric(def_id) => {
-                def_id.hash_stable(hcx, hasher);
-            }
-            ExportedSymbol::Generic(def_id, substs) => {
-                def_id.hash_stable(hcx, hasher);
-                substs.hash_stable(hcx, hasher);
-            }
-            ExportedSymbol::NoDefId(symbol_name) => {
-                symbol_name.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 220560a..27b7697 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -15,6 +15,7 @@
 use crate::ty::{self, TyCtxt};
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -23,8 +24,6 @@
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 // The actual lang items defined come at the end of this file in one handy table.
 // So you probably just want to nip down to the end.
 macro_rules! language_item_table {
@@ -183,8 +182,9 @@
                         self.tcx.sess,
                         span,
                         E0152,
-                        "duplicate lang item found: `{}`.",
-                        name),
+                        "found duplicate lang item `{}`",
+                        name
+                    ),
                     None => {
                         match self.tcx.extern_crate(item_def_id) {
                             Some(ExternCrate {dependency_of, ..}) => {
@@ -204,12 +204,12 @@
                     },
                 };
                 if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
-                    span_note!(&mut err, span, "first defined here.");
+                    err.span_note(span, "first defined here");
                 } else {
                     match self.tcx.extern_crate(original_def_id) {
                         Some(ExternCrate {dependency_of, ..}) => {
                             err.note(&format!(
-                            "first defined in crate `{}` (which `{}` depends on).",
+                            "first defined in crate `{}` (which `{}` depends on)",
                                       self.tcx.crate_name(original_def_id.krate),
                                       self.tcx.crate_name(*dependency_of)));
                         },
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index f2474fa..1176ffc 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -3,23 +3,21 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::lint::{self, in_derive_expansion, Lint};
 use crate::session::{DiagnosticMessageId, Session};
 use crate::ty::{self, TyCtxt};
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_hir::{self, HirId};
+use rustc_session::lint::{self, BuiltinLintDiagnostics, Lint, LintBuffer};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::CRATE_NODE_ID;
 use syntax::attr::{self, ConstStability, Deprecation, RustcDeprecation, Stability};
-use syntax::errors::Applicability;
-use syntax::feature_gate::feature_err_issue;
+use syntax::sess::feature_err_issue;
 
 use std::num::NonZeroU32;
 
@@ -196,13 +194,13 @@
 }
 
 pub fn early_report_deprecation(
-    lint_buffer: &'a mut lint::LintBuffer,
+    lint_buffer: &'a mut LintBuffer,
     message: &str,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
     span: Span,
 ) {
-    if in_derive_expansion(span) {
+    if span.in_derive_expansion() {
         return;
     }
 
@@ -219,7 +217,7 @@
     def_id: DefId,
     hir_id: HirId,
 ) {
-    if in_derive_expansion(span) {
+    if span.in_derive_expansion() {
         return;
     }
 
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index 8e6ac16..5571f8f 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -3,19 +3,18 @@
 use crate::middle::lang_items;
 use crate::session::config;
 
-use crate::hir::intravisit;
-use crate::hir::intravisit::{NestedVisitorMap, Visitor};
+use crate::hir::map::Map;
 use crate::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::PanicStrategy;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 macro_rules! weak_lang_items {
     ($($name:ident, $item:ident, $sym:ident;)*) => (
 
@@ -124,15 +123,20 @@
                 self.items.missing.push(lang_items::$item);
             }
         } else)* {
-            span_err!(self.tcx.sess, span, E0264,
-                      "unknown external lang item: `{}`",
-                      name);
+            struct_span_err!(
+                self.tcx.sess, span, E0264,
+                "unknown external lang item: `{}`",
+                name
+            )
+            .emit();
         }
     }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index f54b923..349dbd7 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -7,8 +7,8 @@
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
-use errors::DiagnosticBuilder;
 use hir::GeneratorKind;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_macros::HashStable;
 use rustc_span::symbol::Symbol;
@@ -16,8 +16,6 @@
 use rustc_target::spec::abi::Abi;
 use std::{any::Any, env, fmt};
 
-use rustc_error_codes::*;
-
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
     /// Already reported a lint or an error for this evaluation.
@@ -33,7 +31,7 @@
             ErrorHandled::Reported => {}
             ErrorHandled::TooGeneric => bug!(
                 "MIR interpretation failed without reporting an error \
-                                              even though it was fully monomorphized"
+                 even though it was fully monomorphized"
             ),
         }
     }
@@ -154,7 +152,7 @@
                 .next()
                 .unwrap_or(lint_root);
             tcx.struct_span_lint_hir(
-                crate::rustc::lint::builtin::CONST_ERR,
+                rustc_session::lint::builtin::CONST_ERR,
                 hir_id,
                 tcx.span,
                 message,
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 99113d6..54e196f 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -119,7 +119,7 @@
 use crate::ty::codec::TyDecoder;
 use crate::ty::layout::{self, Size};
 use crate::ty::subst::GenericArgKind;
-use crate::ty::{self, Instance, TyCtxt};
+use crate::ty::{self, Instance, Ty, TyCtxt};
 use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock};
@@ -131,6 +131,7 @@
 use std::io;
 use std::num::NonZeroU32;
 use std::sync::atomic::{AtomicU32, Ordering};
+use syntax::ast::LitKind;
 
 /// Uniquely identifies one of the following:
 /// - A constant
@@ -147,9 +148,33 @@
     pub promoted: Option<mir::Promoted>,
 }
 
-#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
+/// Input argument for `tcx.lit_to_const`.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)]
+pub struct LitToConstInput<'tcx> {
+    /// The absolute value of the resultant constant.
+    pub lit: &'tcx LitKind,
+    /// The type of the constant.
+    pub ty: Ty<'tcx>,
+    /// If the constant is negative.
+    pub neg: bool,
+}
+
+/// Error type for `tcx.lit_to_const`.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)]
+pub enum LitToConstError {
+    UnparseableFloat,
+    Reported,
+}
+
+#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
 pub struct AllocId(pub u64);
 
+impl fmt::Debug for AllocId {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "alloc{}", self.0)
+    }
+}
+
 impl rustc_serialize::UseSpecializedEncodable for AllocId {}
 impl rustc_serialize::UseSpecializedDecodable for AllocId {}
 
@@ -384,8 +409,8 @@
         let next = self.next_id;
         self.next_id.0 = self.next_id.0.checked_add(1).expect(
             "You overflowed a u64 by incrementing by 1... \
-                     You've just earned yourself a free drink if we ever meet. \
-                     Seriously, how did you do that?!",
+             You've just earned yourself a free drink if we ever meet. \
+             Seriously, how did you do that?!",
         );
         next
     }
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
index 9b0399e..a4974fb 100644
--- a/src/librustc/mir/interpret/pointer.rs
+++ b/src/librustc/mir/interpret/pointer.rs
@@ -133,13 +133,13 @@
 
 impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Pointer<Tag, Id> {
     default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}.{:#x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag)
+        write!(f, "{:?}+{:x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag)
     }
 }
 // Specialization for no tag
 impl<Id: fmt::Debug> fmt::Debug for Pointer<(), Id> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}.{:#x}", self.alloc_id, self.offset.bytes())
+        write!(f, "{:?}+{:x}", self.alloc_id, self.offset.bytes())
     }
 }
 
diff --git a/src/librustc/mir/interpret/queries.rs b/src/librustc/mir/interpret/queries.rs
index 161c9a3..ed57f81 100644
--- a/src/librustc/mir/interpret/queries.rs
+++ b/src/librustc/mir/interpret/queries.rs
@@ -36,11 +36,16 @@
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,
         substs: SubstsRef<'tcx>,
+        promoted: Option<mir::Promoted>,
         span: Option<Span>,
     ) -> ConstEvalResult<'tcx> {
         let instance = ty::Instance::resolve(self, param_env, def_id, substs);
         if let Some(instance) = instance {
-            self.const_eval_instance(param_env, instance, span)
+            if let Some(promoted) = promoted {
+                self.const_eval_promoted(param_env, instance, promoted)
+            } else {
+                self.const_eval_instance(param_env, instance, span)
+            }
         } else {
             Err(ErrorHandled::TooGeneric)
         }
@@ -63,11 +68,11 @@
     /// Evaluate a promoted constant.
     pub fn const_eval_promoted(
         self,
+        param_env: ty::ParamEnv<'tcx>,
         instance: ty::Instance<'tcx>,
         promoted: mir::Promoted,
     ) -> ConstEvalResult<'tcx> {
         let cid = GlobalId { instance, promoted: Some(promoted) };
-        let param_env = ty::ParamEnv::reveal_all();
         self.const_eval_validated(param_env.and(cid))
     }
 }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index ff64302..3a7c650 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 //! MIR datatypes and passes. See the [rustc guide] for more info.
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
@@ -23,14 +21,12 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::graph::{self, GraphSuccessors};
-use rustc_data_structures::sync::Lrc;
 use rustc_index::bit_set::BitMatrix;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
-use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::ops::Index;
@@ -39,13 +35,15 @@
 pub use syntax::ast::Mutability;
 use syntax::ast::Name;
 
-pub use crate::mir::cache::{BodyAndCache, ReadOnlyBodyAndCache};
-pub use crate::mir::interpret::AssertMessage;
+pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache};
+pub use self::interpret::AssertMessage;
+pub use self::query::*;
 pub use crate::read_only;
 
 mod cache;
 pub mod interpret;
 pub mod mono;
+mod query;
 pub mod tcx;
 pub mod traversal;
 pub mod visit;
@@ -166,6 +164,16 @@
 
     /// A span representing this MIR, for error reporting.
     pub span: Span,
+
+    /// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because
+    /// we'd statically know that no thing with interior mutability will ever be available to the
+    /// user without some serious unsafe code.  Now this means that our promoted is actually
+    /// &[(SOME_CELL, 42)] and the MIR using it will do the &promoted[i].1 projection because the
+    /// index may be a runtime value. Such a promoted value is illegal because it has reachable
+    /// interior mutability. This flag just makes this situation very obvious where the previous
+    /// implementation without the flag hid this situation silently.
+    /// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
+    pub ignore_interior_mut_in_const_validation: bool,
 }
 
 impl<'tcx> Body<'tcx> {
@@ -202,10 +210,36 @@
             spread_arg: None,
             var_debug_info,
             span,
+            ignore_interior_mut_in_const_validation: false,
             control_flow_destroyed,
         }
     }
 
+    /// Returns a partially initialized MIR body containing only a list of basic blocks.
+    ///
+    /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
+    /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
+    /// crate.
+    pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
+        Body {
+            phase: MirPhase::Build,
+            basic_blocks,
+            source_scopes: IndexVec::new(),
+            yield_ty: None,
+            generator_drop: None,
+            generator_layout: None,
+            local_decls: IndexVec::new(),
+            user_type_annotations: IndexVec::new(),
+            arg_count: 0,
+            spread_arg: None,
+            span: DUMMY_SP,
+            control_flow_destroyed: Vec::new(),
+            generator_kind: None,
+            var_debug_info: Vec::new(),
+            ignore_interior_mut_in_const_validation: false,
+        }
+    }
+
     #[inline]
     pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
         &self.basic_blocks
@@ -1642,9 +1676,9 @@
 
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
 pub struct Place<'tcx> {
-    pub base: PlaceBase<'tcx>,
+    pub local: Local,
 
     /// projection out of a place (access a field, deref a pointer, etc)
     pub projection: &'tcx List<PlaceElem<'tcx>>,
@@ -1652,58 +1686,6 @@
 
 impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub enum PlaceBase<'tcx> {
-    /// local variable
-    Local(Local),
-
-    /// static or static mut variable
-    Static(Box<Static<'tcx>>),
-}
-
-/// We store the normalized type to avoid requiring normalization when reading MIR
-#[derive(
-    Clone,
-    Debug,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub struct Static<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub kind: StaticKind<'tcx>,
-    /// The `DefId` of the item this static was declared in. For promoted values, usually, this is
-    /// the same as the `DefId` of the `mir::Body` containing the `Place` this promoted appears in.
-    /// However, after inlining, that might no longer be the case as inlined `Place`s are copied
-    /// into the calling frame.
-    pub def_id: DefId,
-}
-
-#[derive(
-    Clone,
-    Debug,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    HashStable,
-    RustcEncodable,
-    RustcDecodable
-)]
-pub enum StaticKind<'tcx> {
-    /// Promoted references consist of an id (`Promoted`) and the substs necessary to monomorphize
-    /// it. Usually, these substs are just the identity substs for the item. However, the inliner
-    /// will adjust these substs when it inlines a function based on the substs at the callsite.
-    Promoted(Promoted, SubstsRef<'tcx>),
-    Static,
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub enum ProjectionElem<V, T> {
@@ -1791,14 +1773,14 @@
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct PlaceRef<'a, 'tcx> {
-    pub base: &'a PlaceBase<'tcx>,
+    pub local: &'a Local,
     pub projection: &'a [PlaceElem<'tcx>],
 }
 
 impl<'tcx> Place<'tcx> {
     // FIXME change this to a const fn by also making List::empty a const fn.
     pub fn return_place() -> Place<'tcx> {
-        Place { base: PlaceBase::Local(RETURN_PLACE), projection: List::empty() }
+        Place { local: RETURN_PLACE, projection: List::empty() }
     }
 
     /// Returns `true` if this `Place` contains a `Deref` projection.
@@ -1815,10 +1797,8 @@
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
         match self.as_ref() {
-            PlaceRef { base: &PlaceBase::Local(local), projection: &[] }
-            | PlaceRef { base: &PlaceBase::Local(local), projection: &[ProjectionElem::Deref] } => {
-                Some(local)
-            }
+            PlaceRef { local, projection: &[] }
+            | PlaceRef { local, projection: &[ProjectionElem::Deref] } => Some(*local),
             _ => None,
         }
     }
@@ -1830,19 +1810,13 @@
     }
 
     pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
-        PlaceRef { base: &self.base, projection: &self.projection }
+        PlaceRef { local: &self.local, projection: &self.projection }
     }
 }
 
 impl From<Local> for Place<'_> {
     fn from(local: Local) -> Self {
-        Place { base: local.into(), projection: List::empty() }
-    }
-}
-
-impl From<Local> for PlaceBase<'_> {
-    fn from(local: Local) -> Self {
-        PlaceBase::Local(local)
+        Place { local, projection: List::empty() }
     }
 }
 
@@ -1853,10 +1827,8 @@
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
         match self {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] }
-            | PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] } => {
-                Some(*local)
-            }
+            PlaceRef { local, projection: [] }
+            | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(**local),
             _ => None,
         }
     }
@@ -1865,7 +1837,7 @@
     /// projections, return `Some(_X)`.
     pub fn as_local(&self) -> Option<Local> {
         match self {
-            PlaceRef { base: PlaceBase::Local(l), projection: [] } => Some(*l),
+            PlaceRef { local, projection: [] } => Some(**local),
             _ => None,
         }
     }
@@ -1887,7 +1859,7 @@
             }
         }
 
-        write!(fmt, "{:?}", self.base)?;
+        write!(fmt, "{:?}", self.local)?;
 
         for elem in self.projection.iter() {
             match elem {
@@ -1931,22 +1903,6 @@
     }
 }
 
-impl Debug for PlaceBase<'_> {
-    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        match *self {
-            PlaceBase::Local(id) => write!(fmt, "{:?}", id),
-            PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static, def_id }) => {
-                write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty)
-            }
-            PlaceBase::Static(box self::Static {
-                ty,
-                kind: StaticKind::Promoted(promoted, _),
-                def_id: _,
-            }) => write!(fmt, "({:?}: {:?})", promoted, ty),
-        }
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Scopes
 
@@ -2648,221 +2604,6 @@
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
-pub enum UnsafetyViolationKind {
-    General,
-    /// Permitted both in `const fn`s and regular `fn`s.
-    GeneralAndConstFn,
-    BorrowPacked(hir::HirId),
-}
-
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UnsafetyViolation {
-    pub source_info: SourceInfo,
-    pub description: Symbol,
-    pub details: Symbol,
-    pub kind: UnsafetyViolationKind,
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UnsafetyCheckResult {
-    /// 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
-    /// used for the "unused_unsafe" lint.
-    pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
-}
-
-rustc_index::newtype_index! {
-    pub struct GeneratorSavedLocal {
-        derive [HashStable]
-        DEBUG_FORMAT = "_{}",
-    }
-}
-
-/// The layout of generator state.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct GeneratorLayout<'tcx> {
-    /// The type of every local stored inside the generator.
-    pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
-
-    /// Which of the above fields are in each variant. Note that one field may
-    /// be stored in multiple variants.
-    pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
-
-    /// Which saved locals are storage-live at the same time. Locals that do not
-    /// have conflicts with each other are allowed to overlap in the computed
-    /// layout.
-    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct BorrowCheckResult<'tcx> {
-    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
-    pub used_mut_upvars: SmallVec<[Field; 8]>,
-}
-
-/// The result of the `mir_const_qualif` query.
-///
-/// Each field corresponds to an implementer of the `Qualif` trait in
-/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
-/// `Qualif`.
-#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ConstQualifs {
-    pub has_mut_interior: bool,
-    pub needs_drop: bool,
-}
-
-/// After we borrow check a closure, we are left with various
-/// requirements that we have inferred between the free regions that
-/// appear in the closure's signature or on its field types. These
-/// requirements are then verified and proved by the closure's
-/// creating function. This struct encodes those requirements.
-///
-/// The requirements are listed as being between various
-/// `RegionVid`. The 0th region refers to `'static`; subsequent region
-/// vids refer to the free regions that appear in the closure (or
-/// generator's) type, in order of appearance. (This numbering is
-/// actually defined by the `UniversalRegions` struct in the NLL
-/// region checker. See for example
-/// `UniversalRegions::closure_mapping`.) Note that we treat the free
-/// regions in the closure's type "as if" they were erased, so their
-/// precise identity is not important, only their position.
-///
-/// Example: If type check produces a closure with the closure substs:
-///
-/// ```text
-/// ClosureSubsts = [
-///     i8,                                  // the "closure kind"
-///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
-///     &'a String,                          // some upvar
-/// ]
-/// ```
-///
-/// here, there is one unique free region (`'a`) but it appears
-/// twice. We would "renumber" each occurrence to a unique vid, as follows:
-///
-/// ```text
-/// ClosureSubsts = [
-///     i8,                                  // the "closure kind"
-///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
-///     &'2 String,                          // some upvar
-/// ]
-/// ```
-///
-/// Now the code might impose a requirement like `'1: '2`. When an
-/// instance of the closure is created, the corresponding free regions
-/// can be extracted from its type and constrained to have the given
-/// outlives relationship.
-///
-/// In some cases, we have to record outlives requirements between
-/// types and regions as well. In that case, if those types include
-/// any regions, those regions are recorded as `ReClosureBound`
-/// 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
-/// internally within the rest of the NLL code).
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ClosureRegionRequirements<'tcx> {
-    /// The number of external regions defined on the closure. In our
-    /// example above, it would be 3 -- one for `'static`, then `'1`
-    /// and `'2`. This is just used for a sanity check later on, to
-    /// make sure that the number of regions we see at the callsite
-    /// matches.
-    pub num_external_vids: usize,
-
-    /// Requirements between the various free regions defined in
-    /// indices.
-    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
-}
-
-/// 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 ...
-    pub subject: ClosureOutlivesSubject<'tcx>,
-
-    // ... must outlive this one.
-    pub outlived_free_region: ty::RegionVid,
-
-    // If not, report an error here ...
-    pub blame_span: Span,
-
-    // ... due to this reason.
-    pub category: ConstraintCategory,
-}
-
-/// 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].
-#[derive(
-    Copy,
-    Clone,
-    Debug,
-    Eq,
-    PartialEq,
-    PartialOrd,
-    Ord,
-    Hash,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub enum ConstraintCategory {
-    Return,
-    Yield,
-    UseAsConst,
-    UseAsStatic,
-    TypeAnnotation,
-    Cast,
-
-    /// A constraint that came from checking the body of a closure.
-    ///
-    /// We try to get the category that the closure used when reporting this.
-    ClosureBounds,
-    CallArgument,
-    CopyBound,
-    SizedBound,
-    Assignment,
-    OpaqueType,
-
-    /// A "boring" constraint (caused by the given location) is one that
-    /// the user probably doesn't want to see described in diagnostics,
-    /// because it is kind of an artifact of the type system setup.
-    /// Example: `x = Foo { field: y }` technically creates
-    /// intermediate regions representing the "type of `Foo { field: y
-    /// }`", and data flows from `y` into those variables, but they
-    /// are not very interesting. The assignment into `x` on the other
-    /// hand might be.
-    Boring,
-    // Boring and applicable everywhere.
-    BoringNoLocation,
-
-    /// A constraint that doesn't correspond to anything the user sees.
-    Internal,
-}
-
-/// 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> {
-    /// Subject is a type, typically a type parameter, but could also
-    /// be a projection. Indicates a requirement like `T: 'a` being
-    /// passed to the caller, where the type here is `T`.
-    ///
-    /// The type here is guaranteed not to contain any free regions at
-    /// present.
-    Ty(Ty<'tcx>),
-
-    /// Subject is a free region from the closure. Indicates a requirement
-    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
-    Region(ty::RegionVid),
-}
-
 /*
  * `TypeFoldable` implementations for MIR types
 */
@@ -3007,27 +2748,11 @@
 
 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        Place { base: self.base.fold_with(folder), projection: self.projection.fold_with(folder) }
+        Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.base.visit_with(visitor) || self.projection.visit_with(visitor)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        match self {
-            PlaceBase::Local(local) => PlaceBase::Local(local.fold_with(folder)),
-            PlaceBase::Static(static_) => PlaceBase::Static(static_.fold_with(folder)),
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        match self {
-            PlaceBase::Local(local) => local.visit_with(visitor),
-            PlaceBase::Static(static_) => (**static_).visit_with(visitor),
-        }
+        self.local.visit_with(visitor) || self.projection.visit_with(visitor)
     }
 }
 
@@ -3042,42 +2767,6 @@
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        Static {
-            ty: self.ty.fold_with(folder),
-            kind: self.kind.fold_with(folder),
-            def_id: self.def_id,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        let Static { ty, kind, def_id: _ } = self;
-
-        ty.visit_with(visitor) || kind.visit_with(visitor)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for StaticKind<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        match self {
-            StaticKind::Promoted(promoted, substs) => {
-                StaticKind::Promoted(promoted.fold_with(folder), substs.fold_with(folder))
-            }
-            StaticKind::Static => StaticKind::Static,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        match self {
-            StaticKind::Promoted(promoted, substs) => {
-                promoted.visit_with(visitor) || substs.visit_with(visitor)
-            }
-            StaticKind::Static => false,
-        }
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         use crate::mir::Rvalue::*;
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 51ce575..475c77a 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -79,7 +79,7 @@
     }
 
     pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
-        let inline_in_all_cgus = tcx
+        let generate_cgu_internal_copies = tcx
             .sess
             .opts
             .debugging_opts
@@ -93,7 +93,7 @@
                 // If this function isn't inlined or otherwise has explicit
                 // linkage, then we'll be creating a globally shared version.
                 if self.explicit_linkage(tcx).is_some()
-                    || !instance.def.requires_local(tcx)
+                    || !instance.def.generates_cgu_internal_copy(tcx)
                     || Some(instance.def_id()) == entry_def_id
                 {
                     return InstantiationMode::GloballyShared { may_conflict: false };
@@ -102,7 +102,7 @@
                 // At this point we don't have explicit linkage and we're an
                 // inlined function. If we're inlining into all CGUs then we'll
                 // be creating a local copy per CGU
-                if inline_in_all_cgus {
+                if generate_cgu_internal_copies {
                     return InstantiationMode::LocalCopy;
                 }
 
diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs
new file mode 100644
index 0000000..34f58ab
--- /dev/null
+++ b/src/librustc/mir/query.rs
@@ -0,0 +1,223 @@
+//! Values computed by queries that use MIR.
+
+use crate::ty::{self, Ty};
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_index::bit_set::BitMatrix;
+use rustc_index::vec::IndexVec;
+use rustc_span::{Span, Symbol};
+use rustc_target::abi::VariantIdx;
+use smallvec::SmallVec;
+
+use super::{Field, SourceInfo};
+
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+pub enum UnsafetyViolationKind {
+    General,
+    /// Permitted both in `const fn`s and regular `fn`s.
+    GeneralAndConstFn,
+    BorrowPacked(hir::HirId),
+}
+
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+pub struct UnsafetyViolation {
+    pub source_info: SourceInfo,
+    pub description: Symbol,
+    pub details: Symbol,
+    pub kind: UnsafetyViolationKind,
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub struct UnsafetyCheckResult {
+    /// 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
+    /// used for the "unused_unsafe" lint.
+    pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
+}
+
+rustc_index::newtype_index! {
+    pub struct GeneratorSavedLocal {
+        derive [HashStable]
+        DEBUG_FORMAT = "_{}",
+    }
+}
+
+/// The layout of generator state.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct GeneratorLayout<'tcx> {
+    /// The type of every local stored inside the generator.
+    pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
+
+    /// Which of the above fields are in each variant. Note that one field may
+    /// be stored in multiple variants.
+    pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
+
+    /// Which saved locals are storage-live at the same time. Locals that do not
+    /// have conflicts with each other are allowed to overlap in the computed
+    /// layout.
+    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct BorrowCheckResult<'tcx> {
+    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
+    pub used_mut_upvars: SmallVec<[Field; 8]>,
+}
+
+/// The result of the `mir_const_qualif` query.
+///
+/// Each field corresponds to an implementer of the `Qualif` trait in
+/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
+/// `Qualif`.
+#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ConstQualifs {
+    pub has_mut_interior: bool,
+    pub needs_drop: bool,
+}
+
+/// After we borrow check a closure, we are left with various
+/// requirements that we have inferred between the free regions that
+/// appear in the closure's signature or on its field types. These
+/// requirements are then verified and proved by the closure's
+/// creating function. This struct encodes those requirements.
+///
+/// The requirements are listed as being between various
+/// `RegionVid`. The 0th region refers to `'static`; subsequent region
+/// vids refer to the free regions that appear in the closure (or
+/// generator's) type, in order of appearance. (This numbering is
+/// actually defined by the `UniversalRegions` struct in the NLL
+/// region checker. See for example
+/// `UniversalRegions::closure_mapping`.) Note that we treat the free
+/// regions in the closure's type "as if" they were erased, so their
+/// precise identity is not important, only their position.
+///
+/// Example: If type check produces a closure with the closure substs:
+///
+/// ```text
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
+///     &'a String,                          // some upvar
+/// ]
+/// ```
+///
+/// here, there is one unique free region (`'a`) but it appears
+/// twice. We would "renumber" each occurrence to a unique vid, as follows:
+///
+/// ```text
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
+///     &'2 String,                          // some upvar
+/// ]
+/// ```
+///
+/// Now the code might impose a requirement like `'1: '2`. When an
+/// instance of the closure is created, the corresponding free regions
+/// can be extracted from its type and constrained to have the given
+/// outlives relationship.
+///
+/// In some cases, we have to record outlives requirements between
+/// types and regions as well. In that case, if those types include
+/// any regions, those regions are recorded as `ReClosureBound`
+/// 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
+/// internally within the rest of the NLL code).
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ClosureRegionRequirements<'tcx> {
+    /// The number of external regions defined on the closure. In our
+    /// example above, it would be 3 -- one for `'static`, then `'1`
+    /// and `'2`. This is just used for a sanity check later on, to
+    /// make sure that the number of regions we see at the callsite
+    /// matches.
+    pub num_external_vids: usize,
+
+    /// Requirements between the various free regions defined in
+    /// indices.
+    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
+}
+
+/// 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 ...
+    pub subject: ClosureOutlivesSubject<'tcx>,
+
+    // ... must outlive this one.
+    pub outlived_free_region: ty::RegionVid,
+
+    // If not, report an error here ...
+    pub blame_span: Span,
+
+    // ... due to this reason.
+    pub category: ConstraintCategory,
+}
+
+/// 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].
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
+pub enum ConstraintCategory {
+    Return,
+    Yield,
+    UseAsConst,
+    UseAsStatic,
+    TypeAnnotation,
+    Cast,
+
+    /// A constraint that came from checking the body of a closure.
+    ///
+    /// We try to get the category that the closure used when reporting this.
+    ClosureBounds,
+    CallArgument,
+    CopyBound,
+    SizedBound,
+    Assignment,
+    OpaqueType,
+
+    /// A "boring" constraint (caused by the given location) is one that
+    /// the user probably doesn't want to see described in diagnostics,
+    /// because it is kind of an artifact of the type system setup.
+    /// Example: `x = Foo { field: y }` technically creates
+    /// intermediate regions representing the "type of `Foo { field: y
+    /// }`", and data flows from `y` into those variables, but they
+    /// are not very interesting. The assignment into `x` on the other
+    /// hand might be.
+    Boring,
+    // Boring and applicable everywhere.
+    BoringNoLocation,
+
+    /// A constraint that doesn't correspond to anything the user sees.
+    Internal,
+}
+
+/// 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> {
+    /// Subject is a type, typically a type parameter, but could also
+    /// be a projection. Indicates a requirement like `T: 'a` being
+    /// passed to the caller, where the type here is `T`.
+    ///
+    /// The type here is guaranteed not to contain any free regions at
+    /// present.
+    Ty(Ty<'tcx>),
+
+    /// Subject is a free region from the closure. Indicates a requirement
+    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
+    Region(ty::RegionVid),
+}
+
+/// The constituent parts of an ADT or array.
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct DestructuredConst<'tcx> {
+    pub variant: VariantIdx,
+    pub fields: &'tcx [&'tcx ty::Const<'tcx>],
+}
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 77f3ff4..e2aac56 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -114,7 +114,7 @@
 
 impl<'tcx> Place<'tcx> {
     pub fn ty_from<D>(
-        base: &PlaceBase<'tcx>,
+        local: &Local,
         projection: &[PlaceElem<'tcx>],
         local_decls: &D,
         tcx: TyCtxt<'tcx>,
@@ -124,26 +124,16 @@
     {
         projection
             .iter()
-            .fold(base.ty(local_decls), |place_ty, elem| place_ty.projection_ty(tcx, elem))
+            .fold(PlaceTy::from_ty(local_decls.local_decls()[*local].ty), |place_ty, elem| {
+                place_ty.projection_ty(tcx, elem)
+            })
     }
 
     pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
     where
         D: HasLocalDecls<'tcx>,
     {
-        Place::ty_from(&self.base, &self.projection, local_decls, tcx)
-    }
-}
-
-impl<'tcx> PlaceBase<'tcx> {
-    pub fn ty<D>(&self, local_decls: &D) -> PlaceTy<'tcx>
-    where
-        D: HasLocalDecls<'tcx>,
-    {
-        match self {
-            PlaceBase::Local(index) => PlaceTy::from_ty(local_decls.local_decls()[*index].ty),
-            PlaceBase::Static(data) => PlaceTy::from_ty(data.ty),
-        }
+        Place::ty_from(&self.local, &self.projection, local_decls, tcx)
     }
 }
 
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 9173c32..4c5db1b 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -164,10 +164,10 @@
             }
 
             fn visit_place_base(&mut self,
-                                base: & $($mutability)? PlaceBase<'tcx>,
+                                local: & $($mutability)? Local,
                                 context: PlaceContext,
                                 location: Location) {
-                self.super_place_base(base, context, location);
+                self.super_place_base(local, context, location);
             }
 
             visit_place_fns!($($mutability)?);
@@ -705,17 +705,10 @@
             }
 
             fn super_place_base(&mut self,
-                                place_base: & $($mutability)? PlaceBase<'tcx>,
+                                local: & $($mutability)? Local,
                                 context: PlaceContext,
                                 location: Location) {
-                match place_base {
-                    PlaceBase::Local(local) => {
-                        self.visit_local(local, context, location);
-                    }
-                    PlaceBase::Static(box Static { kind: _, ty, def_id: _ }) => {
-                        self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
-                    }
-                }
+                self.visit_local(local, context, location);
             }
 
             fn super_local_decl(&mut self,
@@ -848,7 +841,7 @@
             context: PlaceContext,
             location: Location,
         ) {
-            self.visit_place_base(&mut place.base, context, location);
+            self.visit_place_base(&mut place.local, context, location);
 
             if let Some(new_projection) = self.process_projection(&place.projection) {
                 place.projection = self.tcx().intern_place_elems(&new_projection);
@@ -889,23 +882,23 @@
     () => (
         fn visit_projection(
             &mut self,
-            base: &PlaceBase<'tcx>,
+            local: &Local,
             projection: &[PlaceElem<'tcx>],
             context: PlaceContext,
             location: Location,
         ) {
-            self.super_projection(base, projection, context, location);
+            self.super_projection(local, projection, context, location);
         }
 
         fn visit_projection_elem(
             &mut self,
-            base: &PlaceBase<'tcx>,
+            local: &Local,
             proj_base: &[PlaceElem<'tcx>],
             elem: &PlaceElem<'tcx>,
             context: PlaceContext,
             location: Location,
         ) {
-            self.super_projection_elem(base, proj_base, elem, context, location);
+            self.super_projection_elem(local, proj_base, elem, context, location);
         }
 
         fn super_place(
@@ -924,9 +917,9 @@
                 };
             }
 
-            self.visit_place_base(&place.base, context, location);
+            self.visit_place_base(&place.local, context, location);
 
-            self.visit_projection(&place.base,
+            self.visit_projection(&place.local,
                                   &place.projection,
                                   context,
                                   location);
@@ -934,7 +927,7 @@
 
         fn super_projection(
             &mut self,
-            base: &PlaceBase<'tcx>,
+            local: &Local,
             projection: &[PlaceElem<'tcx>],
             context: PlaceContext,
             location: Location,
@@ -942,13 +935,13 @@
             let mut cursor = projection;
             while let [proj_base @ .., elem] = cursor {
                 cursor = proj_base;
-                self.visit_projection_elem(base, cursor, elem, context, location);
+                self.visit_projection_elem(local, cursor, elem, context, location);
             }
         }
 
         fn super_projection_elem(
             &mut self,
-            _base: &PlaceBase<'tcx>,
+            _local: &Local,
             _proj_base: &[PlaceElem<'tcx>],
             elem: &PlaceElem<'tcx>,
             _context: PlaceContext,
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 4a2ec9b..37d5e23 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -1,6 +1,6 @@
 use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
 use crate::mir;
-use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{GlobalId, LitToConstInput};
 use crate::traits;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -82,7 +82,7 @@
             desc { "looking up the native libraries of a linked crate" }
         }
 
-        query lint_levels(_: CrateNum) -> &'tcx lint::LintLevelMap {
+        query lint_levels(_: CrateNum) -> &'tcx LintLevelMap {
             eval_always
             desc { "computing the lint levels for items in this crate" }
         }
@@ -505,10 +505,26 @@
             desc { "extract field of const" }
         }
 
+        /// Destructure a constant ADT or array into its variant indent and its
+        /// field values.
+        query destructure_const(
+            key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
+        ) -> mir::DestructuredConst<'tcx> {
+            no_force
+            desc { "destructure constant" }
+        }
+
         query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
             no_force
             desc { "get a &core::panic::Location referring to a span" }
         }
+
+        query lit_to_const(
+            key: LitToConstInput<'tcx>
+        ) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
+            no_force
+            desc { "converting literal to const" }
+        }
     }
 
     TypeChecking {
@@ -541,6 +557,9 @@
             desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
         }
 
+        /// The `symbol_name` query provides the symbol name for calling a
+        /// given instance from the local crate. In particular, it will also
+        /// look up the correct symbol name of instances from upstream crates.
         query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
             no_force
             desc { "computing the symbol for `{}`", key }
@@ -686,10 +705,6 @@
             fatal_cycle
             desc { "checking if the crate has_panic_handler" }
         }
-        query is_sanitizer_runtime(_: CrateNum) -> bool {
-            fatal_cycle
-            desc { "query a crate is `#![sanitizer_runtime]`" }
-        }
         query is_profiler_runtime(_: CrateNum) -> bool {
             fatal_cycle
             desc { "query a crate is `#![profiler_runtime]`" }
@@ -761,13 +776,47 @@
     }
 
     Codegen {
+        /// The entire set of monomorphizations the local crate can safely link
+        /// to because they are exported from upstream crates. Do not depend on
+        /// this directly, as its value changes anytime a monomorphization gets
+        /// added or removed in any upstream crate. Instead use the narrower
+        /// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
+        /// better, `Instance::upstream_monomorphization()`.
         query upstream_monomorphizations(
             k: CrateNum
         ) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
             desc { "collecting available upstream monomorphizations `{:?}`", k }
         }
+
+        /// Returns the set of upstream monomorphizations available for the
+        /// generic function identified by the given `def_id`. The query makes
+        /// sure to make a stable selection if the same monomorphization is
+        /// available in multiple upstream crates.
+        ///
+        /// You likely want to call `Instance::upstream_monomorphization()`
+        /// instead of invoking this query directly.
         query upstream_monomorphizations_for(_: DefId)
             -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> {}
+
+        /// Returns the upstream crate that exports drop-glue for the given
+        /// type (`substs` is expected to be a single-item list containing the
+        /// type one wants drop-glue for).
+        ///
+        /// This is a subset of `upstream_monomorphizations_for` in order to
+        /// increase dep-tracking granularity. Otherwise adding or removing any
+        /// type with drop-glue in any upstream crate would invalidate all
+        /// functions calling drop-glue of an upstream type.
+        ///
+        /// You likely want to call `Instance::upstream_monomorphization()`
+        /// instead of invoking this query directly.
+        ///
+        /// NOTE: This query could easily be extended to also support other
+        ///       common functions that have are large set of monomorphizations
+        ///       (like `Clone::clone` for example).
+        query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> {
+            desc { "available upstream drop-glue for `{:?}`", substs }
+            no_force
+        }
     }
 
     Other {
@@ -959,6 +1008,11 @@
     }
 
     Linking {
+        /// The list of symbols exported from the given crate.
+        ///
+        /// - All names contained in `exported_symbols(cnum)` are guaranteed to
+        ///   correspond to a publicly visible symbol in `cnum` machine code.
+        /// - The `exported_symbols` sets of different crates do not intersect.
         query exported_symbols(_: CrateNum)
             -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>> {
             desc { "exported_symbols" }
diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs
index 89b28ae..c97c5c2 100644
--- a/src/librustc/traits/auto_trait.rs
+++ b/src/librustc/traits/auto_trait.rs
@@ -337,7 +337,10 @@
                 &Err(SelectionError::Unimplemented) => {
                     if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
                         already_visited.remove(&pred);
-                        self.add_user_pred(&mut user_computed_preds, ty::Predicate::Trait(pred));
+                        self.add_user_pred(
+                            &mut user_computed_preds,
+                            ty::Predicate::Trait(pred, ast::Constness::NotConst),
+                        );
                         predicates.push_back(pred);
                     } else {
                         debug!(
@@ -405,7 +408,7 @@
         let mut should_add_new = true;
         user_computed_preds.retain(|&old_pred| {
             match (&new_pred, old_pred) {
-                (&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => {
+                (&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
                     if new_trait.def_id() == old_trait.def_id() {
                         let new_substs = new_trait.skip_binder().trait_ref.substs;
                         let old_substs = old_trait.skip_binder().trait_ref.substs;
@@ -627,7 +630,7 @@
             // We check this by calling is_of_param on the relevant types
             // from the various possible predicates
             match &predicate {
-                &ty::Predicate::Trait(p) => {
+                &ty::Predicate::Trait(p, _) => {
                     if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
                         && !only_projections
                         && is_new_pred
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index db7cda3..29ea478 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -38,7 +38,7 @@
     pub involves_placeholder: bool,
 }
 
-pub fn add_placeholder_note(err: &mut errors::DiagnosticBuilder<'_>) {
+pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
     err.note(&format!(
         "this behavior recently changed as a result of a bug fix; \
          see rust-lang/rust#56105 for details"
diff --git a/src/librustc/traits/engine.rs b/src/librustc/traits/engine.rs
index 5b80448..84bfc86 100644
--- a/src/librustc/traits/engine.rs
+++ b/src/librustc/traits/engine.rs
@@ -1,6 +1,6 @@
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
-use crate::ty::{self, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_hir::def_id::DefId;
 
 use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
@@ -33,7 +33,7 @@
                 cause,
                 recursion_depth: 0,
                 param_env,
-                predicate: trait_ref.to_predicate(),
+                predicate: trait_ref.without_const().to_predicate(),
             },
         );
     }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
deleted file mode 100644
index 172330d..0000000
--- a/src/librustc/traits/error_reporting.rs
+++ /dev/null
@@ -1,2924 +0,0 @@
-use super::{
-    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
-    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
-    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
-    TraitNotObjectSafe,
-};
-
-use crate::infer::error_reporting::TypeAnnotationNeeded as ErrorCode;
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt};
-use crate::mir::interpret::ErrorHandled;
-use crate::session::DiagnosticMessageId;
-use crate::traits::object_safety_violations;
-use crate::ty::error::ExpectedFound;
-use crate::ty::fast_reject;
-use crate::ty::fold::TypeFolder;
-use crate::ty::subst::Subst;
-use crate::ty::GenericParamDefKind;
-use crate::ty::SubtypePredicate;
-use crate::ty::TypeckTables;
-use crate::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
-use errors::{pluralize, Applicability, DiagnosticBuilder, Style};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::Node;
-use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, sym};
-use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
-use std::fmt;
-use syntax::ast;
-
-use rustc_error_codes::*;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_fulfillment_errors(
-        &self,
-        errors: &[FulfillmentError<'tcx>],
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxHashMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|predicate| ErrorDescriptor {
-                            predicate: predicate.clone(),
-                            index: None,
-                        })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // We want to ignore desugarings here: spans are equivalent even
-            // if one is the result of a desugaring and the other is not.
-            let mut span = error.obligation.cause.span;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate.clone(),
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate.clone());
-        }
-
-        // We do this in 2 passes because we want to display errors in order, though
-        // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed = vec![false; errors.len()];
-        for (_, error_set) in error_map.iter() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(&error2.predicate, &error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(&error.predicate, &error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (error, suppressed) in errors.iter().zip(is_suppressed) {
-            if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
-            }
-        }
-    }
-
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
-            if let ty::Predicate::Trait(implication) = implication {
-                let error = error.to_poly_trait_ref();
-                let implication = implication.to_poly_trait_ref();
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication).is_ok() {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    fn report_fulfillment_error(
-        &self,
-        error: &FulfillmentError<'tcx>,
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        debug!("report_fulfillment_error({:?})", error);
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    &error.obligation,
-                    selection_error,
-                    fallback_has_occurred,
-                    error.points_at_arg_span,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation, body_id);
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    err.clone(),
-                )
-                .emit();
-            }
-        }
-    }
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let err_buf;
-            let mut err = &error.err;
-            let mut values = None;
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            if let ty::Predicate::Projection(ref data) = predicate {
-                let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_bound_vars_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data,
-                );
-                let mut obligations = vec![];
-                let normalized_ty = super::normalize_projection_type(
-                    &mut selcx,
-                    obligation.param_env,
-                    data.projection_ty,
-                    obligation.cause.clone(),
-                    0,
-                    &mut obligations,
-                );
-
-                debug!(
-                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
-                    obligation.cause, obligation.param_env
-                );
-
-                debug!(
-                    "report_projection_error normalized_ty={:?} data.ty={:?}",
-                    normalized_ty, data.ty
-                );
-
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
-                    | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
-
-                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    data.ty,
-                ) {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        data.ty,
-                    )));
-
-                    err_buf = error;
-                    err = &err_buf;
-                }
-            }
-
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
-        });
-    }
-
-    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(t: Ty<'_>) -> Option<u32> {
-            match t.kind {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
-                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Projection(..) => Some(11),
-                ty::Param(..) => Some(12),
-                ty::Opaque(..) => Some(13),
-                ty::Never => Some(14),
-                ty::Adt(adt, ..) => match adt.adt_kind() {
-                    AdtKind::Struct => Some(15),
-                    AdtKind::Union => Some(16),
-                    AdtKind::Enum => Some(17),
-                },
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-            }
-        }
-
-        match (type_category(a), type_category(b)) {
-            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
-                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
-                _ => cat_a == cat_b,
-            },
-            // infer and error can be equated to all types
-            _ => true,
-        }
-    }
-
-    fn impl_similar_to(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId> {
-        let tcx = self.tcx;
-        let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
-        let trait_self_ty = trait_ref.self_ty();
-
-        let mut self_match_impls = vec![];
-        let mut fuzzy_match_impls = vec![];
-
-        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
-            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
-            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
-
-            let impl_self_ty = impl_trait_ref.self_ty();
-
-            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push(def_id);
-
-                if trait_ref
-                    .substs
-                    .types()
-                    .skip(1)
-                    .zip(impl_trait_ref.substs.types().skip(1))
-                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
-                {
-                    fuzzy_match_impls.push(def_id);
-                }
-            }
-        });
-
-        let impl_def_id = if self_match_impls.len() == 1 {
-            self_match_impls[0]
-        } else if fuzzy_match_impls.len() == 1 {
-            fuzzy_match_impls[0]
-        } else {
-            return None;
-        };
-
-        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    /// Used to set on_unimplemented's `ItemContext`
-    /// to be the enclosing (async) block/function/closure
-    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
-        let hir = &self.tcx.hir();
-        let node = hir.find(hir_id)?;
-        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
-            self.describe_generator(*body_id).or_else(|| {
-                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async function"
-                } else {
-                    "a function"
-                })
-            })
-        } else if let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
-            ..
-        }) = &node
-        {
-            self.describe_generator(*body_id).or_else(|| {
-                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
-            })
-        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
-            let parent_hid = hir.get_parent_node(hir_id);
-            if parent_hid != hir_id {
-                return self.describe_enclosure(parent_hid);
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }
-
-    fn on_unimplemented_note(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> OnUnimplementedNote {
-        let def_id =
-            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
-        let trait_ref = *trait_ref.skip_binder();
-
-        let mut flags = vec![];
-        flags.push((
-            sym::item_context,
-            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
-        ));
-
-        match obligation.cause.code {
-            ObligationCauseCode::BuiltinDerivedObligation(..)
-            | ObligationCauseCode::ImplDerivedObligation(..) => {}
-            _ => {
-                // this is a "direct", user-specified, rather than derived,
-                // obligation.
-                flags.push((sym::direct, None));
-            }
-        }
-
-        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
-            // FIXME: maybe also have some way of handling methods
-            // from other traits? That would require name resolution,
-            // which we might want to be some sort of hygienic.
-            //
-            // Currently I'm leaving it for what I need for `try`.
-            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
-                let method = self.tcx.item_name(item);
-                flags.push((sym::from_method, None));
-                flags.push((sym::from_method, Some(method.to_string())));
-            }
-        }
-        if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
-
-        if let Some(k) = obligation.cause.span.desugaring_kind() {
-            flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
-        }
-        let generics = self.tcx.generics_of(def_id);
-        let self_ty = trait_ref.self_ty();
-        // This is also included through the generics list as `Self`,
-        // but the parser won't allow you to use it
-        flags.push((sym::_Self, Some(self_ty.to_string())));
-        if let Some(def) = self_ty.ty_adt_def() {
-            // We also want to be able to select self's original
-            // signature with no type arguments resolved
-            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
-        }
-
-        for param in generics.params.iter() {
-            let value = match param.kind {
-                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                    trait_ref.substs[param.index as usize].to_string()
-                }
-                GenericParamDefKind::Lifetime => continue,
-            };
-            let name = param.name;
-            flags.push((name, Some(value)));
-        }
-
-        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
-            flags.push((sym::crate_local, None));
-        }
-
-        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
-        if self_ty.is_integral() {
-            flags.push((sym::_Self, Some("{integral}".to_owned())));
-        }
-
-        if let ty::Array(aty, len) = self_ty.kind {
-            flags.push((sym::_Self, Some("[]".to_owned())));
-            flags.push((sym::_Self, Some(format!("[{}]", aty))));
-            if let Some(def) = aty.ty_adt_def() {
-                // We also want to be able to select the array's type's original
-                // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
-                ));
-                let tcx = self.tcx;
-                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
-                    ));
-                } else {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
-                    ));
-                }
-            }
-        }
-
-        if let Ok(Some(command)) =
-            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
-        {
-            command.evaluate(self.tcx, trait_ref, &flags[..])
-        } else {
-            OnUnimplementedNote::default()
-        }
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<ty::TraitRef<'tcx>> {
-        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
-        let all_impls = self.tcx.all_impls(trait_ref.def_id());
-
-        match simp {
-            Some(simp) => all_impls
-                .iter()
-                .filter_map(|&def_id| {
-                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
-                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
-                    if let Some(imp_simp) = imp_simp {
-                        if simp != imp_simp {
-                            return None;
-                        }
-                    }
-
-                    Some(imp)
-                })
-                .collect(),
-            None => {
-                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
-            }
-        }
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: Vec<ty::TraitRef<'tcx>>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if impl_candidates.is_empty() {
-            return;
-        }
-
-        let len = impl_candidates.len();
-        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
-
-        let normalize = |candidate| {
-            self.tcx.infer_ctxt().enter(|ref infcx| {
-                let normalized = infcx
-                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                    .normalize(candidate)
-                    .ok();
-                match normalized {
-                    Some(normalized) => format!("\n  {:?}", normalized.value),
-                    None => format!("\n  {:?}", candidate),
-                }
-            })
-        };
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        let mut normalized_impl_candidates =
-            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
-
-        // Sort before taking the `..end` range,
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        normalized_impl_candidates.sort();
-
-        err.help(&format!(
-            "the following implementations were found:{}{}",
-            normalized_impl_candidates[..end].join(""),
-            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
-        ));
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    pub fn report_overflow_error<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<'tcx>,
-    {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            obligation.cause.span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            predicate
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            &obligation.cause.code,
-            &mut vec![],
-        );
-
-        err.emit();
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
-        assert!(cycle.len() > 0);
-
-        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
-
-        self.report_overflow_error(&cycle[0], false);
-    }
-
-    pub fn report_extra_impl_obligation(
-        &self,
-        error_span: Span,
-        item_name: ast::Name,
-        _impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-        requirement: &dyn fmt::Display,
-    ) -> DiagnosticBuilder<'tcx> {
-        let msg = "impl has stricter requirements than trait";
-        let sp = self.tcx.sess.source_map().def_span(error_span);
-
-        let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
-
-        if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
-            let span = self.tcx.sess.source_map().def_span(trait_item_span);
-            err.span_label(span, format!("definition of `{}` from trait", item_name));
-        }
-
-        err.span_label(sp, format!("impl has extra requirement {}", requirement));
-
-        err
-    }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
-        match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => Some(parent_trait_ref.skip_binder().self_ty().to_string()),
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn report_selection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
-        points_at_arg: bool,
-    ) {
-        let tcx = self.tcx;
-        let span = obligation.cause.span;
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                } = obligation.cause.code
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        item_name,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-                match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate) => {
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message) = self
-                            .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(span)
-                            .map(|s| &s == "?")
-                            .unwrap_or(false);
-                        let is_from = format!("{}", trait_ref.print_only_trait_path())
-                            .starts_with("std::convert::From<");
-                        let (message, note) = if is_try && is_from {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                 conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                            )
-                        } else {
-                            (message, note)
-                        };
-
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0277,
-                            "{}",
-                            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.print_only_trait_path(),
-                                    trait_ref.self_ty(),
-                                )
-                            };
-
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            &trait_ref,
-                            points_at_arg,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(ref s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
-                            err.help(&explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-                        if let Some(ref s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
-                        }
-                        if let Some(ref s) = enclosing_scope {
-                            let enclosing_scope_span = tcx.def_span(
-                                tcx.hir()
-                                    .opt_local_def_id(obligation.cause.body_id)
-                                    .unwrap_or_else(|| {
-                                        tcx.hir().body_owner_def_id(hir::BodyId {
-                                            hir_id: obligation.cause.body_id,
-                                        })
-                                    }),
-                            );
-
-                            err.span_label(enclosing_scope_span, s.as_str());
-                        }
-
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
-                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
-                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
-                        self.note_version_mismatch(&mut err, &trait_ref);
-
-                        // Try to report a help message
-                        if !trait_ref.has_infer_types()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
-                        {
-                            // If a where-clause may be useful, remind the
-                            // user that they can add it.
-                            //
-                            // don't display an on-unimplemented note, as
-                            // these notes will often be of the form
-                            //     "the type `T` can't be frobnicated"
-                            // which is somewhat confusing.
-                            self.suggest_restricting_param_bound(
-                                &mut err,
-                                &trait_ref,
-                                obligation.cause.body_id,
-                            );
-                        } else {
-                            if !have_alt_message {
-                                // Can't show anything else useful, try to find similar impls.
-                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
-                                self.report_similar_impl_candidates(impl_candidates, &mut err);
-                            }
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                &trait_ref,
-                                points_at_arg,
-                            );
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
-                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_unit(),
-                                    &trait_pred.trait_ref.substs[1..],
-                                );
-                                trait_pred
-                            });
-                            let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(predicate),
-                                ..obligation.clone()
-                            };
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.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.",
-                                );
-                            }
-                        }
-
-                        err
-                    }
-
-                    ty::Predicate::Subtype(ref predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = self.resolve_vars_if_possible(predicate);
-                        let err = self
-                            .region_outlives_predicate(&obligation.cause, &predicate)
-                            .err()
-                            .unwrap();
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0279,
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err,
-                        )
-                    }
-
-                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
-                        )
-                    }
-
-                    ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = object_safety_violations(self.tcx, trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
-                        let closure_span = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            closure_span,
-                            E0525,
-                            "expected a closure that implements the `{}` trait, \
-                             but this closure only implements `{}`",
-                            kind,
-                            found_kind
-                        );
-
-                        err.span_label(
-                            closure_span,
-                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
-                        );
-                        err.span_label(
-                            obligation.cause.span,
-                            format!("the requirement to implement `{}` derives from here", kind),
-                        );
-
-                        // Additional context information explaining why the closure only implements
-                        // a particular trait.
-                        if let Some(tables) = self.in_progress_tables {
-                            let tables = tables.borrow();
-                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnOnce` because it moves the \
-                                         variable `{}` out of its environment",
-                                            name
-                                        ),
-                                    );
-                                }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnMut` because it mutates the \
-                                         variable `{}` here",
-                                            name
-                                        ),
-                                    );
-                                }
-                                _ => {}
-                            }
-                        }
-
-                        err.emit();
-                        return;
-                    }
-
-                    ty::Predicate::WellFormed(ty) => {
-                        if !self.tcx.sess.opts.debugging_opts.chalk {
-                            // WF predicates cannot themselves make
-                            // errors. They can only block due to
-                            // ambiguity; otherwise, they always
-                            // degenerate into other obligations
-                            // (which may fail).
-                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                        } else {
-                            // FIXME: we'll need a better message which takes into account
-                            // which bounds actually failed to hold.
-                            self.tcx.sess.struct_span_err(
-                                span,
-                                &format!("the type `{}` is not well-formed (chalk)", ty),
-                            )
-                        }
-                    }
-
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
-                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
-                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
-
-                if expected_trait_ref.self_ty().references_error() {
-                    return;
-                }
-
-                let found_trait_ty = found_trait_ref.self_ty();
-
-                let found_did = match found_trait_ty.kind {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
-                    ty::Adt(def, _) => Some(def.did),
-                    _ => None,
-                };
-
-                let found_span = found_did
-                    .and_then(|did| self.tcx.hir().span_if_local(did))
-                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
-
-                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
-                    // We check closures twice, with obligations flowing in different directions,
-                    // but we want to complain about them only once.
-                    return;
-                }
-
-                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
-                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
-                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
-                    _ => vec![ArgKind::empty()],
-                };
-
-                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
-                let expected = match expected_ty.kind {
-                    ty::Tuple(ref tys) => tys
-                        .iter()
-                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
-                        .collect(),
-                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
-                };
-
-                if found.len() == expected.len() {
-                    self.report_closure_arg_mismatch(
-                        span,
-                        found_span,
-                        found_trait_ref,
-                        expected_trait_ref,
-                    )
-                } else {
-                    let (closure_span, found) = found_did
-                        .and_then(|did| self.tcx.hir().get_if_local(did))
-                        .map(|node| {
-                            let (found_span, found) = self.get_fn_like_arguments(node);
-                            (Some(found_span), found)
-                        })
-                        .unwrap_or((found_span, found));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span,
-                        expected,
-                        found,
-                        found_trait_ty.is_closure(),
-                    )
-                }
-            }
-
-            TraitNotObjectSafe(did) => {
-                let violations = object_safety_violations(self.tcx, did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            // already reported in the query
-            ConstEvalFailure(err) => {
-                if let ErrorHandled::TooGeneric = err {
-                    // Silence this error, as it can be produced during intermediate steps
-                    // when a constant is not yet able to be evaluated (but will be later).
-                    return;
-                }
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    &format!("constant in type had an ignored error: {:?}", err),
-                );
-                return;
-            }
-
-            Overflow => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-        };
-
-        self.note_obligation_cause(&mut err, obligation);
-
-        err.emit();
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) {
-        let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
-                if trait_impl.is_none() {
-                    trait_impl = Some(impl_def_id);
-                }
-            });
-            trait_impl
-        };
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
-        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
-            .iter()
-            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
-            .collect();
-        for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "Perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-            }
-        }
-    }
-    fn suggest_restricting_param_bound(
-        &self,
-        mut err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'_>,
-        body_id: hir::HirId,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (param_ty, projection) = match &self_ty.kind {
-            ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
-            _ => return,
-        };
-
-        let suggest_restriction =
-            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
-                let span = generics.where_clause.span_for_predicates_or_empty_place();
-                if !span.from_expansion() && span.desugaring_kind().is_none() {
-                    err.span_suggestion(
-                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
-                        &format!("consider further restricting {}", msg),
-                        format!(
-                            "{} {} ",
-                            if !generics.where_clause.predicates.is_empty() {
-                                ","
-                            } else {
-                                " where"
-                            },
-                            trait_ref.to_predicate(),
-                        ),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            };
-
-        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
-        //        don't suggest `T: Sized + ?Sized`.
-        let mut hir_id = body_id;
-        while let Some(node) = self.tcx.hir().find(hir_id) {
-            match node {
-                hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                }) if param_ty && self_ty == self.tcx.types.self_param => {
-                    // Restricting `Self` for a single method.
-                    suggest_restriction(&generics, "`Self`", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
-                | hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::ImplItem(hir::ImplItem {
-                    generics,
-                    kind: hir::ImplItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
-                    ..
-                }) if projection.is_some() => {
-                    // Missing associated type bound.
-                    suggest_restriction(&generics, "the associated type", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Enum(_, generics), span, ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Union(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_, generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TyAlias(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TraitAlias(generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
-                    span,
-                    ..
-                })
-                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
-                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
-                    if param_ty =>
-                {
-                    // Missing generic type parameter bound.
-                    let param_name = self_ty.to_string();
-                    let constraint = trait_ref.print_only_trait_path().to_string();
-                    if suggest_constraining_type_param(
-                        generics,
-                        &mut err,
-                        &param_name,
-                        &constraint,
-                        self.tcx.sess.source_map(),
-                        *span,
-                    ) {
-                        return;
-                    }
-                }
-
-                hir::Node::Crate => return,
-
-                _ => {}
-            }
-
-            hir_id = self.tcx.hir().get_parent_item(hir_id);
-        }
-    }
-
-    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
-    /// suggestion to borrow the initializer in order to use have a slice instead.
-    fn suggest_borrow_on_unsized_slice(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-    ) {
-        if let &ObligationCauseCode::VariableType(hir_id) = code {
-            let parent_node = self.tcx.hir().get_parent_node(hir_id);
-            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
-                if let Some(ref expr) = local.init {
-                    if let hir::ExprKind::Index(_, _) = expr.kind {
-                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-                            err.span_suggestion(
-                                expr.span,
-                                "consider borrowing here",
-                                format!("&{}", snippet),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    fn mk_obligation_for_def_id(
-        &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.to_predicate())
-    }
-
-    /// Given a closure's `DefId`, return the given name of the closure.
-    ///
-    /// This doesn't account for reassignments, but it's only used for suggestions.
-    fn get_closure_name(
-        &self,
-        def_id: DefId,
-        err: &mut DiagnosticBuilder<'_>,
-        msg: &str,
-    ) -> Option<String> {
-        let get_name =
-            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
-                // Get the local name of this closure. This can be inaccurate because
-                // of the possibility of reassignment, but this should be good enough.
-                match &kind {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
-                        Some(format!("{}", name))
-                    }
-                    _ => {
-                        err.note(&msg);
-                        None
-                    }
-                }
-            };
-
-        let hir = self.tcx.hir();
-        let hir_id = hir.as_local_hir_id(def_id)?;
-        let parent_node = hir.get_parent_node(hir_id);
-        match hir.find(parent_node) {
-            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
-                get_name(err, &local.pat.kind)
-            }
-            // Different to previous arm because one is `&hir::Local` and the other
-            // is `P<hir::Local>`.
-            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
-            _ => return None,
-        }
-    }
-
-    /// We tried to apply the bound to an `fn` or closure. 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`.
-    fn suggest_fn_call(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (def_id, output_ty, callable) = match self_ty.kind {
-            ty::Closure(def_id, substs) => {
-                (def_id, self.closure_sig(def_id, substs).output(), "closure")
-            }
-            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
-            _ => return,
-        };
-        let msg = format!("use parentheses to call the {}", callable);
-
-        let obligation = self.mk_obligation_for_def_id(
-            trait_ref.def_id(),
-            output_ty.skip_binder(),
-            obligation.cause.clone(),
-            obligation.param_env,
-        );
-
-        match self.evaluate_obligation(&obligation) {
-            Ok(EvaluationResult::EvaluatedToOk)
-            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
-            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
-            _ => return,
-        }
-        let hir = self.tcx.hir();
-        // Get the name of the callable and the arguments to be used in the suggestion.
-        let snippet = match hir.get_if_local(def_id) {
-            Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
-                ..
-            })) => {
-                err.span_label(*span, "consider calling this closure");
-                let name = match self.get_closure_name(def_id, err, &msg) {
-                    Some(name) => name,
-                    None => return,
-                };
-                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                format!("{}({})", name, args)
-            }
-            Some(hir::Node::Item(hir::Item {
-                ident,
-                kind: hir::ItemKind::Fn(.., body_id),
-                ..
-            })) => {
-                err.span_label(ident.span, "consider calling this function");
-                let body = hir.body(*body_id);
-                let args = body
-                    .params
-                    .iter()
-                    .map(|arg| match &arg.pat.kind {
-                        hir::PatKind::Binding(_, _, ident, None)
-                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
-                        // should suggest a method call.
-                        if ident.name != kw::SelfLower => ident.to_string(),
-                        _ => "_".to_string(),
-                    })
-                    .collect::<Vec<_>>()
-                    .join(", ");
-                format!("{}({})", ident, args)
-            }
-            _ => return,
-        };
-        if points_at_arg {
-            // When the obligation error has been ensured to have been caused by
-            // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
-            err.span_suggestion(
-                obligation.cause.span,
-                &msg,
-                snippet,
-                Applicability::HasPlaceholders,
-            );
-        } else {
-            err.help(&format!("{}: `{}`", msg, snippet));
-        }
-    }
-
-    fn suggest_add_reference_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-        has_custom_message: bool,
-    ) -> bool {
-        if !points_at_arg {
-            return false;
-        }
-
-        let span = obligation.cause.span;
-        let param_env = obligation.param_env;
-        let trait_ref = trait_ref.skip_binder();
-
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
-            // Try to apply the original trait binding obligation by borrowing.
-            let self_ty = trait_ref.self_ty();
-            let found = self_ty.to_string();
-            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
-            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
-            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
-            let new_obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
-            if self.predicate_must_hold_modulo_regions(&new_obligation) {
-                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    // We have a very specific type of error, where just borrowing this argument
-                    // might solve the problem. In cases like this, the important part is the
-                    // original type obligation, not the last one that failed, which is arbitrary.
-                    // Because of this, we modify the error to refer to the original obligation and
-                    // return early in the caller.
-                    let msg = format!(
-                        "the trait bound `{}: {}` is not satisfied",
-                        found,
-                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                    );
-                    if has_custom_message {
-                        err.note(&msg);
-                    } else {
-                        err.message = vec![(msg, Style::NoStyle)];
-                    }
-                    if snippet.starts_with('&') {
-                        // This is already a literal borrow and the obligation is failing
-                        // somewhere else in the obligation chain. Do not suggest non-sense.
-                        return false;
-                    }
-                    err.span_label(
-                        span,
-                        &format!(
-                            "expected an implementor of trait `{}`",
-                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                        ),
-                    );
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{}", snippet),
-                        Applicability::MaybeIncorrect,
-                    );
-                    return true;
-                }
-            }
-        }
-        false
-    }
-
-    /// 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(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let trait_ref = trait_ref.skip_binder();
-        let span = obligation.cause.span;
-
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') =
-                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
-            {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-
-            let mut trait_type = trait_ref.self_ty();
-
-            for refs_remaining in 0..refs_number {
-                if let ty::Ref(_, t_type, _) = trait_type.kind {
-                    trait_type = t_type;
-
-                    let new_obligation = self.mk_obligation_for_def_id(
-                        trait_ref.def_id,
-                        trait_type,
-                        ObligationCause::dummy(),
-                        obligation.param_env,
-                    );
-
-                    if self.predicate_may_hold(&new_obligation) {
-                        let sp = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-
-                        let remove_refs = refs_remaining + 1;
-                        let format_str =
-                            format!("consider removing {} leading `&`-references", remove_refs);
-
-                        err.span_suggestion_short(
-                            sp,
-                            &format_str,
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                        break;
-                    }
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-    /// Check if the trait bound is implemented for a different mutability and note it in the
-    /// final error.
-    fn suggest_change_mut(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let span = obligation.cause.span;
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') =
-                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
-            {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-            let trait_ref = self.resolve_vars_if_possible(trait_ref);
-            if trait_ref.has_infer_types() {
-                // Do not ICE while trying to find if a reborrow would succeed on a trait with
-                // unresolved bindings.
-                return;
-            }
-
-            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
-                let trait_type = match mutability {
-                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
-                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
-                };
-
-                let new_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.skip_binder().def_id,
-                    trait_type,
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                );
-
-                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
-                {
-                    let sp = self
-                        .tcx
-                        .sess
-                        .source_map()
-                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
-                        err.span_suggestion(
-                            sp,
-                            "consider changing this borrow's mutability",
-                            "&mut ".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        err.note(&format!(
-                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
-                            trait_ref.print_only_trait_path(),
-                            trait_type,
-                            trait_ref.skip_binder().self_ty(),
-                        ));
-                    }
-                }
-            }
-        }
-    }
-
-    fn suggest_semicolon_removal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
-        {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && "()" == &trait_ref.self_ty().to_string()
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                        err.span_label(sp, "consider removing this semicolon");
-                    }
-                }
-            }
-        }
-    }
-
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
-        match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                self.tcx
-                    .hir()
-                    .body(id)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        let snippet = self
-                                            .tcx
-                                            .sess
-                                            .source_map()
-                                            .span_to_snippet(pat.span)
-                                            .unwrap();
-                                        (snippet, "_".to_owned())
-                                    })
-                                    .collect::<Vec<_>>(),
-                            )
-                        } else {
-                            let name =
-                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
-                            ArgKind::Arg(name, "_".to_owned())
-                        }
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                span,
-                kind: hir::ImplItemKind::Method(ref sig, _),
-                ..
-            })
-            | Node::TraitItem(&hir::TraitItem {
-                span,
-                kind: hir::TraitItemKind::Method(ref sig, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.clone().kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data
-                    .ctor_hir_id()
-                    .map(|hir_id| self.tcx.hir().span(hir_id))
-                    .unwrap_or(DUMMY_SP);
-                let span = self.tcx.sess.source_map().def_span(span);
-
-                (span, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {:?}", node),
-        }
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    pub fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-    ) -> DiagnosticBuilder<'tcx> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
-            match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {}", found_str));
-
-            // move |_| { ... }
-            // ^^^^^^^^-- def_span
-            //
-            // move |_| { ... }
-            // ^^^^^-- prefix
-            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
-            // move |_| { ... }
-            //      ^^^-- pipe_span
-            let pipe_span =
-                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion(
-                    pipe_span,
-                    &format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        if expected_args.len() < 2 { "" } else { "s" }
-                    ),
-                    format!("|{}|", underscores),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{}|", sugg),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-        }
-
-        err
-    }
-
-    fn report_closure_arg_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_ref: ty::PolyTraitRef<'tcx>,
-        found: ty::PolyTraitRef<'tcx>,
-    ) -> DiagnosticBuilder<'tcx> {
-        fn build_fn_sig_string<'tcx>(tcx: TyCtxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> String {
-            let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
-                    ::std::iter::once(inputs),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            };
-            ty::Binder::bind(sig).to_string()
-        }
-
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0631,
-            "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
-        );
-
-        let found_str = format!(
-            "expected signature of `{}`",
-            build_fn_sig_string(self.tcx, found.skip_binder())
-        );
-        err.span_label(span, found_str);
-
-        let found_span = found_span.unwrap_or(span);
-        let expected_str = format!(
-            "found signature of `{}`",
-            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
-        );
-        err.span_label(found_span, expected_str);
-
-        err
-    }
-}
-
-pub fn recursive_type_with_infinite_size_error(
-    tcx: TyCtxt<'tcx>,
-    type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
-    assert!(type_def_id.is_local());
-    let span = tcx.hir().span_if_local(type_def_id).unwrap();
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
-    err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
-}
-
-pub fn report_object_safety_error(
-    tcx: TyCtxt<'tcx>,
-    span: Span,
-    trait_def_id: DefId,
-    violations: Vec<ObjectSafetyViolation>,
-) -> DiagnosticBuilder<'tcx> {
-    let trait_str = tcx.def_path_str(trait_def_id);
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0038,
-        "the trait `{}` cannot be made into an object",
-        trait_str
-    );
-    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
-
-    let mut reported_violations = FxHashSet::default();
-    for violation in violations {
-        if reported_violations.insert(violation.clone()) {
-            match violation.span() {
-                Some(span) => err.span_label(span, violation.error_msg()),
-                None => err.note(&violation.error_msg()),
-            };
-        }
-    }
-
-    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
-        // Avoid emitting error caused by non-existing method (#58734)
-        err.cancel();
-    }
-
-    err
-}
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn maybe_report_ambiguity(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        body_id: Option<hir::BodyId>,
-    ) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(
-            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
-            predicate, obligation, body_id, obligation.cause.code,
-        );
-
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
-
-        let mut err = match predicate {
-            ty::Predicate::Trait(ref data) => {
-                let trait_ref = data.to_poly_trait_ref();
-                let self_ty = trait_ref.self_ty();
-                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized".  It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and dont add the obligations to
-                // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
-                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                if let (Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _)) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
-                {
-                    let generics = self.tcx.generics_of(*def_id);
-                    if !generics.params.is_empty() && !snippet.ends_with('>') {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |              --------- - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot resolve `_: Tt`
-
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                if generics.params.len() > 1 { "s" } else { "" },
-                            ),
-                            format!(
-                                "{}::<{}>",
-                                snippet,
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
-                err
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if ty.references_error() || self.tcx.sess.has_errors() {
-                    return;
-                }
-                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
-            }
-
-            ty::Predicate::Subtype(ref data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
-            }
-            ty::Predicate::Projection(ref data) => {
-                let trait_ref = data.to_poly_trait_ref(self.tcx);
-                let self_ty = trait_ref.self_ty();
-                if predicate.references_error() {
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                err
-            }
-
-            _ => {
-                if self.tcx.sess.has_errors() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot resolve `{}`",
-                    predicate,
-                );
-                err.span_label(span, &format!("cannot resolve `{}`", predicate));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'a, 'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
-                    let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let mut selcx = SelectionContext::new(self);
-
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let cleaned_pred = super::project::normalize(
-                &mut selcx,
-                param_env,
-                ObligationCause::dummy(),
-                &cleaned_pred,
-            )
-            .value;
-
-            let obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    fn note_obligation_cause(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        // First, attempt to add note to this error with an async-await-specific
-        // message, and fall back to regular note otherwise.
-        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                &obligation.cause.code,
-                &mut vec![],
-            );
-        }
-    }
-
-    /// Adds an async-await specific note to the diagnostic when the future does not implement
-    /// an auto trait because of a captured type.
-    ///
-    /// ```ignore (diagnostic)
-    /// note: future does not implement `Qux` as this value is used across an await
-    ///   --> $DIR/issue-64130-3-other.rs:17:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
-    /// is "replaced" with a different message and a more specific error.
-    ///
-    /// ```ignore (diagnostic)
-    /// error: future cannot be sent between threads safely
-    ///   --> $DIR/issue-64130-2-send.rs:21:5
-    ///    |
-    /// LL | fn is_send<T: Send>(t: T) { }
-    ///    |    -------    ---- required by this bound in `is_send`
-    /// ...
-    /// LL |     is_send(bar());
-    ///    |     ^^^^^^^ future returned by `bar` is not send
-    ///    |
-    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
-    ///            implemented for `Foo`
-    /// note: future is not send as this value is used across an await
-    ///   --> $DIR/issue-64130-2-send.rs:15:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// Returns `true` if an async-await specific note was added to the diagnostic.
-    fn maybe_note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
-                obligation.cause.span={:?}",
-            obligation.predicate, obligation.cause.span
-        );
-        let source_map = self.tcx.sess.source_map();
-
-        // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for a generator to be present.
-        //
-        // When a future does not implement a trait because of a captured type in one of the
-        // generators somewhere in the call stack, then the result is a chain of obligations.
-        //
-        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
-        // future is passed as an argument to a function C which requires a `Send` type, then the
-        // chain looks something like this:
-        //
-        // - `BuiltinDerivedObligation` with a generator witness (B)
-        // - `BuiltinDerivedObligation` with a generator (B)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with a generator witness (A)
-        // - `BuiltinDerivedObligation` with a generator (A)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BindingObligation` with `impl_send (Send requirement)
-        //
-        // The first obligation in the chain is the most useful and has the generator that captured
-        // the type. The last generator has information about where the bound was introduced. At
-        // least one generator should be present for this diagnostic to be modified.
-        let (mut trait_ref, mut target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(p) => {
-                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
-            }
-            _ => (None, None),
-        };
-        let mut generator = None;
-        let mut last_generator = None;
-        let mut next_code = Some(&obligation.cause.code);
-        while let Some(code) = next_code {
-            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
-            match code {
-                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
-                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
-                    let ty = derived_obligation.parent_trait_ref.self_ty();
-                    debug!(
-                        "maybe_note_obligation_cause_for_async_await: \
-                            parent_trait_ref={:?} self_ty.kind={:?}",
-                        derived_obligation.parent_trait_ref, ty.kind
-                    );
-
-                    match ty.kind {
-                        ty::Generator(did, ..) => {
-                            generator = generator.or(Some(did));
-                            last_generator = Some(did);
-                        }
-                        ty::GeneratorWitness(..) => {}
-                        _ if generator.is_none() => {
-                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
-                            target_ty = Some(ty);
-                        }
-                        _ => {}
-                    }
-
-                    next_code = Some(derived_obligation.parent_code.as_ref());
-                }
-                _ => break,
-            }
-        }
-
-        // Only continue if a generator was found.
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
-                target_ty={:?}",
-            generator, trait_ref, target_ty
-        );
-        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
-            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
-                (generator_did, trait_ref, target_ty)
-            }
-            _ => return false,
-        };
-
-        let span = self.tcx.def_span(generator_did);
-
-        // Do not ICE on closure typeck (#66868).
-        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
-            return false;
-        }
-
-        // Get the tables from the infcx if the generator is the function we are
-        // currently type-checking; otherwise, get them by performing a query.
-        // This is needed to avoid cycles.
-        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
-             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
-            generator_did,
-            generator_did_root,
-            in_progress_tables.as_ref().map(|t| t.local_id_root),
-            span
-        );
-        let query_tables;
-        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
-            Some(t) if t.local_id_root == Some(generator_did_root) => t,
-            _ => {
-                query_tables = self.tcx.typeck_tables_of(generator_did);
-                &query_tables
-            }
-        };
-
-        // Look for a type inside the generator interior that matches the target type to get
-        // a span.
-        let target_ty_erased = self.tcx.erase_regions(&target_ty);
-        let target_span = tables
-            .generator_interior_types
-            .iter()
-            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
-                // Careful: the regions for types that appear in the
-                // generator interior are not generally known, so we
-                // want to erase them when comparing (and anyway,
-                // `Send` and other bounds are generally unaffected by
-                // the choice of region).  When erasing regions, we
-                // also have to erase late-bound regions. This is
-                // because the types that appear in the generator
-                // interior generally contain "bound regions" to
-                // represent regions that are part of the suspended
-                // generator frame. Bound regions are preserved by
-                // `erase_regions` and so we must also call
-                // `erase_late_bound_regions`.
-                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
-                let ty_erased = self.tcx.erase_regions(&ty_erased);
-                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
-                debug!(
-                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
-                        target_ty_erased={:?} eq={:?}",
-                    ty_erased, target_ty_erased, eq
-                );
-                eq
-            })
-            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }| {
-                (span, source_map.span_to_snippet(*span), scope_span)
-            });
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
-                generator_interior_types={:?} target_span={:?}",
-            target_ty, tables.generator_interior_types, target_span
-        );
-        if let Some((target_span, Ok(snippet), scope_span)) = target_span {
-            self.note_obligation_cause_for_async_await(
-                err,
-                *target_span,
-                scope_span,
-                snippet,
-                generator_did,
-                last_generator,
-                trait_ref,
-                target_ty,
-                tables,
-                obligation,
-                next_code,
-            );
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Unconditionally adds the diagnostic note described in
-    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
-    fn note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        target_span: Span,
-        scope_span: &Option<Span>,
-        snippet: String,
-        first_generator: DefId,
-        last_generator: Option<DefId>,
-        trait_ref: ty::TraitRef<'_>,
-        target_ty: Ty<'tcx>,
-        tables: &ty::TypeckTables<'_>,
-        obligation: &PredicateObligation<'tcx>,
-        next_code: Option<&ObligationCauseCode<'tcx>>,
-    ) {
-        let source_map = self.tcx.sess.source_map();
-
-        let is_async_fn = self
-            .tcx
-            .parent(first_generator)
-            .map(|parent_did| self.tcx.asyncness(parent_did))
-            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
-            .unwrap_or(false);
-        let is_async_move = self
-            .tcx
-            .hir()
-            .as_local_hir_id(first_generator)
-            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
-            .map(|body_id| self.tcx.hir().body(body_id))
-            .and_then(|body| body.generator_kind())
-            .map(|generator_kind| match generator_kind {
-                hir::GeneratorKind::Async(..) => true,
-                _ => false,
-            })
-            .unwrap_or(false);
-        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
-
-        // Special case the primary error message when send or sync is the trait that was
-        // not implemented.
-        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
-        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
-        let trait_explanation = if is_send || is_sync {
-            let (trait_name, trait_verb) =
-                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
-
-            err.clear_code();
-            err.set_primary_message(format!(
-                "future cannot be {} between threads safely",
-                trait_verb
-            ));
-
-            let original_span = err.span.primary_span().unwrap();
-            let mut span = MultiSpan::from_span(original_span);
-
-            let message = if let Some(name) = last_generator
-                .and_then(|generator_did| self.tcx.parent(generator_did))
-                .and_then(|parent_did| self.tcx.hir().as_local_hir_id(parent_did))
-                .and_then(|parent_hir_id| self.tcx.hir().opt_name(parent_hir_id))
-            {
-                format!("future returned by `{}` is not {}", name, trait_name)
-            } else {
-                format!("future is not {}", trait_name)
-            };
-
-            span.push_span_label(original_span, message);
-            err.set_span(span);
-
-            format!("is not {}", trait_name)
-        } else {
-            format!("does not implement `{}`", trait_ref.print_only_trait_path())
-        };
-
-        // Look at the last interior type to get a span for the `.await`.
-        let await_span = tables.generator_interior_types.iter().map(|i| i.span).last().unwrap();
-        let mut span = MultiSpan::from_span(await_span);
-        span.push_span_label(
-            await_span,
-            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
-        );
-
-        span.push_span_label(target_span, format!("has type `{}`", target_ty));
-
-        // If available, use the scope span to annotate the drop location.
-        if let Some(scope_span) = scope_span {
-            span.push_span_label(
-                source_map.end_point(*scope_span),
-                format!("`{}` is later dropped here", snippet),
-            );
-        }
-
-        err.span_note(
-            span,
-            &format!(
-                "future {} as this value is used across an {}",
-                trait_explanation, await_or_yield,
-            ),
-        );
-
-        // Add a note for the item obligation that remains - normally a note pointing to the
-        // bound that introduced the obligation (e.g. `T: Send`).
-        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
-        self.note_obligation_cause_code(
-            err,
-            &obligation.predicate,
-            next_code.unwrap(),
-            &mut Vec::new(),
-        );
-    }
-
-    fn note_obligation_cause_code<T>(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        predicate: &T,
-        cause_code: &ObligationCauseCode<'tcx>,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-    ) where
-        T: fmt::Display,
-    {
-        let tcx = self.tcx;
-        match *cause_code {
-            ObligationCauseCode::ExprAssignable
-            | ObligationCauseCode::MatchExpressionArm { .. }
-            | ObligationCauseCode::Pattern { .. }
-            | ObligationCauseCode::IfExpression { .. }
-            | ObligationCauseCode::IfExpressionWithNoElse
-            | ObligationCauseCode::MainFunctionType
-            | ObligationCauseCode::StartFunctionType
-            | ObligationCauseCode::IntrinsicType
-            | ObligationCauseCode::MethodReceiver
-            | ObligationCauseCode::ReturnNoExpression
-            | ObligationCauseCode::MiscObligation => {}
-            ObligationCauseCode::SliceOrArrayElem => {
-                err.note("slice and array elements must have `Sized` type");
-            }
-            ObligationCauseCode::TupleElem => {
-                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,));
-            }
-            ObligationCauseCode::ReferenceOutlivesReferent(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,
-                ));
-            }
-            ObligationCauseCode::ItemObligation(item_def_id) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by `{}`", item_name);
-
-                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
-                    let sp = tcx.sess.source_map().def_span(sp);
-                    err.span_label(sp, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by this bound in `{}`", item_name);
-                if let Some(ident) = tcx.opt_item_name(item_def_id) {
-                    err.span_label(ident.span, "");
-                }
-                if span != DUMMY_SP {
-                    err.span_label(span, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::ObjectCastObligation(object_ty) => {
-                err.note(&format!(
-                    "required for the cast to the object type `{}`",
-                    self.ty_to_string(object_ty)
-                ));
-            }
-            ObligationCauseCode::Coercion { source: _, target } => {
-                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
-            }
-            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
-                err.note(
-                    "the `Copy` trait is required because the \
-                          repeated element will be copied",
-                );
-                if suggest_const_in_array_repeat_expressions {
-                    err.note(
-                        "this array initializer can be evaluated at compile-time, for more \
-                              information, see issue \
-                              https://github.com/rust-lang/rust/issues/49147",
-                    );
-                    if tcx.sess.opts.unstable_features.is_nightly_build() {
-                        err.help(
-                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
-                                  crate attributes to enable",
-                        );
-                    }
-                }
-            }
-            ObligationCauseCode::VariableType(_) => {
-                err.note("all local variables must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedArgumentType => {
-                err.note("all function arguments must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedReturnType => {
-                err.note(
-                    "the return type of a function must have a \
-                          statically known size",
-                );
-            }
-            ObligationCauseCode::SizedYieldType => {
-                err.note(
-                    "the yield type of a generator must have a \
-                          statically known size",
-                );
-            }
-            ObligationCauseCode::AssignmentLhsSized => {
-                err.note("the left-hand-side of an assignment must have a statically known size");
-            }
-            ObligationCauseCode::TupleInitializerSized => {
-                err.note("tuples must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::StructInitializerSized => {
-                err.note("structs must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
-                AdtKind::Struct => {
-                    if last {
-                        err.note(
-                            "the last field of a packed struct may only have a \
-                                      dynamically sized type if it does not need drop to be run",
-                        );
-                    } else {
-                        err.note(
-                            "only the last field of a struct may have a dynamically \
-                                      sized type",
-                        );
-                    }
-                }
-                AdtKind::Union => {
-                    err.note("no field of a union may have a dynamically sized type");
-                }
-                AdtKind::Enum => {
-                    err.note("no field of an enum variant may have a dynamically sized type");
-                }
-            },
-            ObligationCauseCode::ConstSized => {
-                err.note("constant expressions must have a statically known size");
-            }
-            ObligationCauseCode::ConstPatternStructural => {
-                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
-            }
-            ObligationCauseCode::SharedStatic => {
-                err.note("shared static variables must have a type that implements `Sync`");
-            }
-            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                let ty = parent_trait_ref.skip_binder().self_ty();
-                err.note(&format!("required because it appears within the type `{}`", ty));
-                obligated_types.push(ty);
-
-                let parent_predicate = parent_trait_ref.to_predicate();
-                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
-                    self.note_obligation_cause_code(
-                        err,
-                        &parent_predicate,
-                        &data.parent_code,
-                        obligated_types,
-                    );
-                }
-            }
-            ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                err.note(&format!(
-                    "required because of the requirements on the impl of `{}` for `{}`",
-                    parent_trait_ref.print_only_trait_path(),
-                    parent_trait_ref.skip_binder().self_ty()
-                ));
-                let parent_predicate = parent_trait_ref.to_predicate();
-                self.note_obligation_cause_code(
-                    err,
-                    &parent_predicate,
-                    &data.parent_code,
-                    obligated_types,
-                );
-            }
-            ObligationCauseCode::CompareImplMethodObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the impl method \
-                              but not on the corresponding trait method",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::CompareImplTypeObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the associated impl type\
-                     but not on the corresponding associated trait type",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::ReturnType
-            | ObligationCauseCode::ReturnValue(_)
-            | ObligationCauseCode::BlockTailExpression(_) => (),
-            ObligationCauseCode::TrivialBound => {
-                err.help("see issue #48214");
-                if tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help(
-                        "add `#![feature(trivial_bounds)]` to the \
-                              crate attributes to enable",
-                    );
-                }
-            }
-            ObligationCauseCode::AssocTypeBound(ref data) => {
-                err.span_label(data.original, "associated type defined here");
-                if let Some(sp) = data.impl_span {
-                    err.span_label(sp, "in this `impl` item");
-                }
-                for sp in &data.bounds {
-                    err.span_label(*sp, "restricted in this bound");
-                }
-            }
-        }
-    }
-
-    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit.get();
-        let suggested_limit = current_limit * 2;
-        err.help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-            suggested_limit
-        ));
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
-                return true;
-            }
-        }
-        false
-    }
-}
-
-/// Summarizes information
-#[derive(Clone)]
-pub enum ArgKind {
-    /// An argument of non-tuple type. Parameters are (name, ty)
-    Arg(String, String),
-
-    /// An argument of tuple type. For a "found" argument, the span is
-    /// the locationo in the source of the pattern. For a "expected"
-    /// argument, it will be None. The vector is a list of (name, ty)
-    /// strings for the components of the tuple.
-    Tuple(Option<Span>, Vec<(String, String)>),
-}
-
-impl ArgKind {
-    fn empty() -> ArgKind {
-        ArgKind::Arg("_".to_owned(), "_".to_owned())
-    }
-
-    /// Creates an `ArgKind` from the expected type of an
-    /// argument. It has no name (`_`) and an optional source span.
-    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
-        match t.kind {
-            ty::Tuple(ref tys) => ArgKind::Tuple(
-                span,
-                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
-            ),
-            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
-        }
-    }
-}
-
-/// Suggest restricting a type param with a new bound.
-pub fn suggest_constraining_type_param(
-    generics: &hir::Generics<'_>,
-    err: &mut DiagnosticBuilder<'_>,
-    param_name: &str,
-    constraint: &str,
-    source_map: &SourceMap,
-    span: Span,
-) -> bool {
-    let restrict_msg = "consider further restricting this bound";
-    if let Some(param) =
-        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
-    {
-        if param_name.starts_with("impl ") {
-            // `impl Trait` in argument:
-            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
-            err.span_suggestion(
-                param.span,
-                restrict_msg,
-                // `impl CurrentTrait + MissingTrait`
-                format!("{} + {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
-            // If there are no bounds whatsoever, suggest adding a constraint
-            // to the type parameter:
-            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
-            err.span_suggestion(
-                param.span,
-                "consider restricting this bound",
-                format!("{}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else if !generics.where_clause.predicates.is_empty() {
-            // There is a `where` clause, so suggest expanding it:
-            // `fn foo<T>(t: T) where T: Debug {}` →
-            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
-            err.span_suggestion(
-                generics.where_clause.span().unwrap().shrink_to_hi(),
-                &format!("consider further restricting type parameter `{}`", param_name),
-                format!(", {}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            // If there is no `where` clause lean towards constraining to the
-            // type parameter:
-            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
-            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
-            let sp = param.span.with_hi(span.hi());
-            let span = source_map.span_through_char(sp, ':');
-            if sp != param.span && sp != span {
-                // Only suggest if we have high certainty that the span
-                // covers the colon in `foo<T: Trait>`.
-                err.span_suggestion(
-                    span,
-                    restrict_msg,
-                    format!("{}: {} + ", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            } else {
-                err.span_label(
-                    param.span,
-                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
-                );
-            }
-        }
-        return true;
-    }
-    false
-}
diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs
new file mode 100644
index 0000000..cdb5077
--- /dev/null
+++ b/src/librustc/traits/error_reporting/mod.rs
@@ -0,0 +1,1430 @@
+pub mod on_unimplemented;
+pub mod suggestions;
+
+use super::{
+    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
+    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
+    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
+    TraitNotObjectSafe,
+};
+
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{self, InferCtxt};
+use crate::mir::interpret::ErrorHandled;
+use crate::session::DiagnosticMessageId;
+use crate::traits::object_safety_violations;
+use crate::ty::error::ExpectedFound;
+use crate::ty::fast_reject;
+use crate::ty::fold::TypeFolder;
+use crate::ty::SubtypePredicate;
+use crate::ty::{
+    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+};
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::source_map::SourceMap;
+use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::fmt;
+use syntax::ast;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    pub fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        #[derive(Debug)]
+        struct ErrorDescriptor<'tcx> {
+            predicate: ty::Predicate<'tcx>,
+            index: Option<usize>, // None if this is an old error
+        }
+
+        let mut error_map: FxHashMap<_, Vec<_>> = self
+            .reported_trait_errors
+            .borrow()
+            .iter()
+            .map(|(&span, predicates)| {
+                (
+                    span,
+                    predicates
+                        .iter()
+                        .map(|predicate| ErrorDescriptor {
+                            predicate: predicate.clone(),
+                            index: None,
+                        })
+                        .collect(),
+                )
+            })
+            .collect();
+
+        for (index, error) in errors.iter().enumerate() {
+            // We want to ignore desugarings here: spans are equivalent even
+            // if one is the result of a desugaring and the other is not.
+            let mut span = error.obligation.cause.span;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
+            }
+
+            error_map.entry(span).or_default().push(ErrorDescriptor {
+                predicate: error.obligation.predicate.clone(),
+                index: Some(index),
+            });
+
+            self.reported_trait_errors
+                .borrow_mut()
+                .entry(span)
+                .or_default()
+                .push(error.obligation.predicate.clone());
+        }
+
+        // We do this in 2 passes because we want to display errors in order, though
+        // maybe it *is* better to sort errors by span or something.
+        let mut is_suppressed = vec![false; errors.len()];
+        for (_, error_set) in error_map.iter() {
+            // We want to suppress "duplicate" errors with the same span.
+            for error in error_set {
+                if let Some(index) = error.index {
+                    // Suppress errors that are either:
+                    // 1) strictly implied by another error.
+                    // 2) implied by an error with a smaller index.
+                    for error2 in error_set {
+                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+                            // Avoid errors being suppressed by already-suppressed
+                            // errors, to prevent all errors from being suppressed
+                            // at once.
+                            continue;
+                        }
+
+                        if self.error_implies(&error2.predicate, &error.predicate)
+                            && !(error2.index >= error.index
+                                && self.error_implies(&error.predicate, &error2.predicate))
+                        {
+                            info!("skipping {:?} (implied by {:?})", error, error2);
+                            is_suppressed[index] = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        for (error, suppressed) in errors.iter().zip(is_suppressed) {
+            if !suppressed {
+                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
+            }
+        }
+    }
+
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
+        if cond == error {
+            return true;
+        }
+
+        let (cond, error) = match (cond, error) {
+            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
+            _ => {
+                // FIXME: make this work in other cases too.
+                return false;
+            }
+        };
+
+        for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
+            if let ty::Predicate::Trait(implication, _) = implication {
+                let error = error.to_poly_trait_ref();
+                let implication = implication.to_poly_trait_ref();
+                // FIXME: I'm just not taking associated types at all here.
+                // Eventually I'll need to implement param-env-aware
+                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
+                let param_env = ty::ParamEnv::empty();
+                if self.can_sub(param_env, error, implication).is_ok() {
+                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        debug!("report_fulfillment_error({:?})", error);
+        match error.code {
+            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+                self.report_selection_error(
+                    &error.obligation,
+                    selection_error,
+                    fallback_has_occurred,
+                    error.points_at_arg_span,
+                );
+            }
+            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+                self.report_projection_error(&error.obligation, e);
+            }
+            FulfillmentErrorCode::CodeAmbiguity => {
+                self.maybe_report_ambiguity(&error.obligation, body_id);
+            }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    err.clone(),
+                )
+                .emit();
+            }
+        }
+    }
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    ) {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+
+        if predicate.references_error() {
+            return;
+        }
+
+        self.probe(|_| {
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data,
+                );
+                let mut obligations = vec![];
+                let normalized_ty = super::normalize_projection_type(
+                    &mut selcx,
+                    obligation.param_env,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0,
+                    &mut obligations,
+                );
+
+                debug!(
+                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
+                    obligation.cause, obligation.param_env
+                );
+
+                debug!(
+                    "report_projection_error normalized_ty={:?} data.ty={:?}",
+                    normalized_ty, data.ty
+                );
+
+                let is_normalized_ty_expected = match &obligation.cause.code {
+                    ObligationCauseCode::ItemObligation(_)
+                    | ObligationCauseCode::BindingObligation(_, _)
+                    | ObligationCauseCode::ObjectCastObligation(_) => false,
+                    _ => true,
+                };
+
+                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
+                    is_normalized_ty_expected,
+                    normalized_ty,
+                    data.ty,
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        data.ty,
+                    )));
+
+                    err_buf = error;
+                    err = &err_buf;
+                }
+            }
+
+            let msg = format!("type mismatch resolving `{}`", predicate);
+            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
+            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                let mut diag = struct_span_err!(
+                    self.tcx.sess,
+                    obligation.cause.span,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate
+                );
+                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                self.note_obligation_cause(&mut diag, obligation);
+                diag.emit();
+            }
+        });
+    }
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+        /// returns the fuzzy category of a given type, or None
+        /// if the type can be equated to any type.
+        fn type_category(t: Ty<'_>) -> Option<u32> {
+            match t.kind {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
+                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Projection(..) => Some(11),
+                ty::Param(..) => Some(12),
+                ty::Opaque(..) => Some(13),
+                ty::Never => Some(14),
+                ty::Adt(adt, ..) => match adt.adt_kind() {
+                    AdtKind::Struct => Some(15),
+                    AdtKind::Union => Some(16),
+                    AdtKind::Enum => Some(17),
+                },
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+            }
+        }
+
+        match (type_category(a), type_category(b)) {
+            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
+                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
+                _ => cat_a == cat_b,
+            },
+            // infer and error can be equated to all types
+            _ => true,
+        }
+    }
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
+            hir::GeneratorKind::Gen => "a generator",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+        })
+    }
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>> {
+        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
+        let all_impls = self.tcx.all_impls(trait_ref.def_id());
+
+        match simp {
+            Some(simp) => all_impls
+                .iter()
+                .filter_map(|&def_id| {
+                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
+                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
+                    if let Some(imp_simp) = imp_simp {
+                        if simp != imp_simp {
+                            return None;
+                        }
+                    }
+
+                    Some(imp)
+                })
+                .collect(),
+            None => {
+                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
+            }
+        }
+    }
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if impl_candidates.is_empty() {
+            return;
+        }
+
+        let len = impl_candidates.len();
+        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
+
+        let normalize = |candidate| {
+            self.tcx.infer_ctxt().enter(|ref infcx| {
+                let normalized = infcx
+                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                    .normalize(candidate)
+                    .ok();
+                match normalized {
+                    Some(normalized) => format!("\n  {:?}", normalized.value),
+                    None => format!("\n  {:?}", candidate),
+                }
+            })
+        };
+
+        // Sort impl candidates so that ordering is consistent for UI tests.
+        let mut normalized_impl_candidates =
+            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
+        normalized_impl_candidates.sort();
+
+        err.help(&format!(
+            "the following implementations were found:{}{}",
+            normalized_impl_candidates[..end].join(""),
+            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
+        ));
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    pub fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>,
+    {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            obligation.cause.span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            predicate
+        );
+
+        if suggest_increasing_limit {
+            self.suggest_new_overflow_limit(&mut err);
+        }
+
+        self.note_obligation_cause_code(
+            &mut err,
+            &obligation.predicate,
+            &obligation.cause.code,
+            &mut vec![],
+        );
+
+        err.emit();
+        self.tcx.sess.abort_if_errors();
+        bug!();
+    }
+
+    /// Reports that a cycle was detected which led to overflow and halts
+    /// compilation. This is equivalent to `report_overflow_error` except
+    /// that we can give a more helpful error message (and, in particular,
+    /// we do not suggest increasing the overflow limit, which is not
+    /// going to help).
+    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
+        assert!(cycle.len() > 0);
+
+        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
+
+        self.report_overflow_error(&cycle[0], false);
+    }
+
+    pub fn report_extra_impl_obligation(
+        &self,
+        error_span: Span,
+        item_name: ast::Name,
+        _impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+        requirement: &dyn fmt::Display,
+    ) -> DiagnosticBuilder<'tcx> {
+        let msg = "impl has stricter requirements than trait";
+        let sp = self.tcx.sess.source_map().def_span(error_span);
+
+        let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
+
+        if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
+            let span = self.tcx.sess.source_map().def_span(trait_item_span);
+            err.span_label(span, format!("definition of `{}` from trait", item_name));
+        }
+
+        err.span_label(sp, format!("impl has extra requirement {}", requirement));
+
+        err
+    }
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
+        match code {
+            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                match self.get_parent_trait_ref(&data.parent_code) {
+                    Some(t) => Some(t),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span =
+                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
+                }
+            }
+            _ => None,
+        }
+    }
+
+    pub fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    ) {
+        let tcx = self.tcx;
+        let span = obligation.cause.span;
+
+        let mut err = match *error {
+            SelectionError::Unimplemented => {
+                if let ObligationCauseCode::CompareImplMethodObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                }
+                | ObligationCauseCode::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                } = obligation.cause.code
+                {
+                    self.report_extra_impl_obligation(
+                        span,
+                        item_name,
+                        impl_item_def_id,
+                        trait_item_def_id,
+                        &format!("`{}`", obligation.predicate),
+                    )
+                    .emit();
+                    return;
+                }
+                match obligation.predicate {
+                    ty::Predicate::Trait(ref trait_predicate, _) => {
+                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+
+                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                            return;
+                        }
+                        let trait_ref = trait_predicate.to_poly_trait_ref();
+                        let (post_message, pre_message, type_def) = self
+                            .get_parent_trait_ref(&obligation.cause.code)
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
+                            .unwrap_or_default();
+
+                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
+                            self.on_unimplemented_note(trait_ref, obligation);
+                        let have_alt_message = message.is_some() || label.is_some();
+                        let is_try = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_to_snippet(span)
+                            .map(|s| &s == "?")
+                            .unwrap_or(false);
+                        let is_from = format!("{}", trait_ref.print_only_trait_path())
+                            .starts_with("std::convert::From<");
+                        let (message, note) = if is_try && is_from {
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error to `{}`",
+                                    trait_ref.self_ty(),
+                                )),
+                                Some(
+                                    "the question mark operation (`?`) implicitly performs a \
+                                     conversion on the error value using the `From` trait"
+                                        .to_owned(),
+                                ),
+                            )
+                        } else {
+                            (message, note)
+                        };
+
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0277,
+                            "{}",
+                            message.unwrap_or_else(|| format!(
+                                "the trait bound `{}` is not satisfied{}",
+                                trait_ref.without_const().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.print_only_trait_path(),
+                                    trait_ref.self_ty(),
+                                )
+                            };
+
+                        if self.suggest_add_reference_to_arg(
+                            &obligation,
+                            &mut err,
+                            &trait_ref,
+                            points_at_arg,
+                            have_alt_message,
+                        ) {
+                            self.note_obligation_cause(&mut err, obligation);
+                            err.emit();
+                            return;
+                        }
+                        if let Some(ref s) = label {
+                            // If it has a custom `#[rustc_on_unimplemented]`
+                            // error message, let's display it as the label!
+                            err.span_label(span, s.as_str());
+                            err.help(&explanation);
+                        } else {
+                            err.span_label(span, explanation);
+                        }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
+                        if let Some(ref s) = note {
+                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
+                            err.note(s.as_str());
+                        }
+                        if let Some(ref s) = enclosing_scope {
+                            let enclosing_scope_span = tcx.def_span(
+                                tcx.hir()
+                                    .opt_local_def_id(obligation.cause.body_id)
+                                    .unwrap_or_else(|| {
+                                        tcx.hir().body_owner_def_id(hir::BodyId {
+                                            hir_id: obligation.cause.body_id,
+                                        })
+                                    }),
+                            );
+
+                            err.span_label(enclosing_scope_span, s.as_str());
+                        }
+
+                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
+                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
+                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
+                        self.note_version_mismatch(&mut err, &trait_ref);
+                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
+                            err.emit();
+                            return;
+                        }
+
+                        // Try to report a help message
+                        if !trait_ref.has_infer_types()
+                            && self.predicate_can_apply(obligation.param_env, trait_ref)
+                        {
+                            // If a where-clause may be useful, remind the
+                            // user that they can add it.
+                            //
+                            // don't display an on-unimplemented note, as
+                            // these notes will often be of the form
+                            //     "the type `T` can't be frobnicated"
+                            // which is somewhat confusing.
+                            self.suggest_restricting_param_bound(
+                                &mut err,
+                                &trait_ref,
+                                obligation.cause.body_id,
+                            );
+                        } else {
+                            if !have_alt_message {
+                                // Can't show anything else useful, try to find similar impls.
+                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
+                                self.report_similar_impl_candidates(impl_candidates, &mut err);
+                            }
+                            self.suggest_change_mut(
+                                &obligation,
+                                &mut err,
+                                &trait_ref,
+                                points_at_arg,
+                            );
+                        }
+
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occurred, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
+                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
+                                    self.tcx.mk_unit(),
+                                    &trait_pred.trait_ref.substs[1..],
+                                );
+                                trait_pred
+                            });
+                            let unit_obligation = Obligation {
+                                predicate: ty::Predicate::Trait(
+                                    predicate,
+                                    ast::Constness::NotConst,
+                                ),
+                                ..obligation.clone()
+                            };
+                            if self.predicate_may_hold(&unit_obligation) {
+                                err.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.",
+                                );
+                            }
+                        }
+
+                        err
+                    }
+
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::Predicate::RegionOutlives(ref predicate) => {
+                        let predicate = self.resolve_vars_if_possible(predicate);
+                        let err = self
+                            .region_outlives_predicate(&obligation.cause, &predicate)
+                            .err()
+                            .unwrap();
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0279,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err,
+                        )
+                    }
+
+                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0280,
+                            "the requirement `{}` is not satisfied",
+                            predicate
+                        )
+                    }
+
+                    ty::Predicate::ObjectSafe(trait_def_id) => {
+                        let violations = object_safety_violations(self.tcx, trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                    }
+
+                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
+                        let closure_span = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
+                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            closure_span,
+                            E0525,
+                            "expected a closure that implements the `{}` trait, \
+                             but this closure only implements `{}`",
+                            kind,
+                            found_kind
+                        );
+
+                        err.span_label(
+                            closure_span,
+                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
+                        );
+                        err.span_label(
+                            obligation.cause.span,
+                            format!("the requirement to implement `{}` derives from here", kind),
+                        );
+
+                        // Additional context information explaining why the closure only implements
+                        // a particular trait.
+                        if let Some(tables) = self.in_progress_tables {
+                            let tables = tables.borrow();
+                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
+                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnOnce` because it moves the \
+                                         variable `{}` out of its environment",
+                                            name
+                                        ),
+                                    );
+                                }
+                                (ty::ClosureKind::FnMut, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnMut` because it mutates the \
+                                         variable `{}` here",
+                                            name
+                                        ),
+                                    );
+                                }
+                                _ => {}
+                            }
+                        }
+
+                        err.emit();
+                        return;
+                    }
+
+                    ty::Predicate::WellFormed(ty) => {
+                        if !self.tcx.sess.opts.debugging_opts.chalk {
+                            // WF predicates cannot themselves make
+                            // errors. They can only block due to
+                            // ambiguity; otherwise, they always
+                            // degenerate into other obligations
+                            // (which may fail).
+                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+                        } else {
+                            // FIXME: we'll need a better message which takes into account
+                            // which bounds actually failed to hold.
+                            self.tcx.sess.struct_span_err(
+                                span,
+                                &format!("the type `{}` is not well-formed (chalk)", ty),
+                            )
+                        }
+                    }
+
+                    ty::Predicate::ConstEvaluatable(..) => {
+                        // Errors for `ConstEvaluatable` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+                }
+            }
+
+            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
+                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
+                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
+
+                if expected_trait_ref.self_ty().references_error() {
+                    return;
+                }
+
+                let found_trait_ty = found_trait_ref.self_ty();
+
+                let found_did = match found_trait_ty.kind {
+                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Adt(def, _) => Some(def.did),
+                    _ => None,
+                };
+
+                let found_span = found_did
+                    .and_then(|did| self.tcx.hir().span_if_local(did))
+                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
+
+                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
+                    // We check closures twice, with obligations flowing in different directions,
+                    // but we want to complain about them only once.
+                    return;
+                }
+
+                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
+
+                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
+                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
+                    _ => vec![ArgKind::empty()],
+                };
+
+                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+                let expected = match expected_ty.kind {
+                    ty::Tuple(ref tys) => tys
+                        .iter()
+                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
+                        .collect(),
+                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
+                };
+
+                if found.len() == expected.len() {
+                    self.report_closure_arg_mismatch(
+                        span,
+                        found_span,
+                        found_trait_ref,
+                        expected_trait_ref,
+                    )
+                } else {
+                    let (closure_span, found) = found_did
+                        .and_then(|did| self.tcx.hir().get_if_local(did))
+                        .map(|node| {
+                            let (found_span, found) = self.get_fn_like_arguments(node);
+                            (Some(found_span), found)
+                        })
+                        .unwrap_or((found_span, found));
+
+                    self.report_arg_count_mismatch(
+                        span,
+                        closure_span,
+                        expected,
+                        found,
+                        found_trait_ty.is_closure(),
+                    )
+                }
+            }
+
+            TraitNotObjectSafe(did) => {
+                let violations = object_safety_violations(self.tcx, did);
+                report_object_safety_error(self.tcx, span, did, violations)
+            }
+
+            ConstEvalFailure(ErrorHandled::TooGeneric) => {
+                // In this instance, we have a const expression containing an unevaluated
+                // generic parameter. We have no idea whether this expression is valid or
+                // not (e.g. it might result in an error), but we don't want to just assume
+                // that it's okay, because that might result in post-monomorphisation time
+                // errors. The onus is really on the caller to provide values that it can
+                // prove are well-formed.
+                let mut err = self
+                    .tcx
+                    .sess
+                    .struct_span_err(span, "constant expression depends on a generic parameter");
+                // FIXME(const_generics): we should suggest to the user how they can resolve this
+                // issue. However, this is currently not actually possible
+                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
+                err.note("this may fail depending on what value the parameter takes");
+                err
+            }
+
+            // Already reported in the query.
+            ConstEvalFailure(ErrorHandled::Reported) => {
+                self.tcx
+                    .sess
+                    .delay_span_bug(span, &format!("constant in type had an ignored error"));
+                return;
+            }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
+        };
+
+        self.note_obligation_cause(&mut err, obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+
+        err.emit();
+    }
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) {
+        let get_trait_impl = |trait_def_id| {
+            let mut trait_impl = None;
+            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
+                if trait_impl.is_none() {
+                    trait_impl = Some(impl_def_id);
+                }
+            });
+            trait_impl
+        };
+        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
+        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
+        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
+            .iter()
+            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
+            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
+            .collect();
+        for trait_with_same_path in traits_with_same_path {
+            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
+                let impl_span = self.tcx.def_span(impl_def_id);
+                err.span_help(impl_span, "trait impl with same name found");
+                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+                let crate_msg = format!(
+                    "perhaps two different versions of crate `{}` are being used?",
+                    trait_crate
+                );
+                err.note(&crate_msg);
+            }
+        }
+    }
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx> {
+        let new_trait_ref =
+            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
+        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
+    }
+}
+
+pub fn recursive_type_with_infinite_size_error(
+    tcx: TyCtxt<'tcx>,
+    type_def_id: DefId,
+) -> DiagnosticBuilder<'tcx> {
+    assert!(type_def_id.is_local());
+    let span = tcx.hir().span_if_local(type_def_id).unwrap();
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0072,
+        "recursive type `{}` has infinite size",
+        tcx.def_path_str(type_def_id)
+    );
+    err.span_label(span, "recursive type has infinite size");
+    err.help(&format!(
+        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+                           at some point to make `{}` representable",
+        tcx.def_path_str(type_def_id)
+    ));
+    err
+}
+
+pub fn report_object_safety_error(
+    tcx: TyCtxt<'tcx>,
+    span: Span,
+    trait_def_id: DefId,
+    violations: Vec<ObjectSafetyViolation>,
+) -> DiagnosticBuilder<'tcx> {
+    let trait_str = tcx.def_path_str(trait_def_id);
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0038,
+        "the trait `{}` cannot be made into an object",
+        trait_str
+    );
+    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
+
+    let mut reported_violations = FxHashSet::default();
+    for violation in violations {
+        if reported_violations.insert(violation.clone()) {
+            match violation.span() {
+                Some(span) => err.span_label(span, violation.error_msg()),
+                None => err.note(&violation.error_msg()),
+            };
+        }
+    }
+
+    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
+        // Avoid emitting error caused by non-existing method (#58734)
+        err.cancel();
+    }
+
+    err
+}
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    ) {
+        // Unable to successfully determine, probably means
+        // insufficient type information, but could mean
+        // ambiguous impls. The latter *ought* to be a
+        // coherence violation, so we don't report it here.
+
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let span = obligation.cause.span;
+
+        debug!(
+            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
+            predicate, obligation, body_id, obligation.cause.code,
+        );
+
+        // Ambiguity errors are often caused as fallout from earlier
+        // errors. So just ignore them if this infcx is tainted.
+        if self.is_tainted_by_errors() {
+            return;
+        }
+
+        let mut err = match predicate {
+            ty::Predicate::Trait(ref data, _) => {
+                let trait_ref = data.to_poly_trait_ref();
+                let self_ty = trait_ref.self_ty();
+                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
+
+                if predicate.references_error() {
+                    return;
+                }
+                // Typically, this ambiguity should only happen if
+                // there are unresolved type inference variables
+                // (otherwise it would suggest a coherence
+                // failure). But given #21974 that is not necessarily
+                // the case -- we can have multiple where clauses that
+                // are only distinguished by a region, which results
+                // in an ambiguity even when all types are fully
+                // known, since we don't dispatch based on region
+                // relationships.
+
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized".  It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
+                // avoid inundating the user with unnecessary errors, but we now
+                // check upstream for type errors and dont add the obligations to
+                // begin with in those cases.
+                if self
+                    .tcx
+                    .lang_items()
+                    .sized_trait()
+                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
+                {
+                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                } else if let (
+                    Ok(ref snippet),
+                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                ) =
+                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
+                {
+                    let generics = self.tcx.generics_of(*def_id);
+                    if !generics.params.is_empty() && !snippet.ends_with('>') {
+                        // FIXME: To avoid spurious suggestions in functions where type arguments
+                        // where already supplied, we check the snippet to make sure it doesn't
+                        // end with a turbofish. Ideally we would have access to a `PathSegment`
+                        // instead. Otherwise we would produce the following output:
+                        //
+                        // error[E0283]: type annotations needed
+                        //   --> $DIR/issue-54954.rs:3:24
+                        //    |
+                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+                        //    |                        |
+                        //    |                        cannot infer type
+                        //    |                        help: consider specifying the type argument
+                        //    |                        in the function call:
+                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
+                        // ...
+                        // LL |     const fn const_val<T: Sized>() -> usize {
+                        //    |              --------- - required by this bound in `Tt::const_val`
+                        //    |
+                        //    = note: cannot resolve `_: Tt`
+
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider specifying the type argument{} in the function call",
+                                if generics.params.len() > 1 { "s" } else { "" },
+                            ),
+                            format!(
+                                "{}::<{}>",
+                                snippet,
+                                generics
+                                    .params
+                                    .iter()
+                                    .map(|p| p.name.to_string())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            ),
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+                }
+                err
+            }
+
+            ty::Predicate::WellFormed(ty) => {
+                // Same hacky approach as above to avoid deluging user
+                // with error messages.
+                if ty.references_error() || self.tcx.sess.has_errors() {
+                    return;
+                }
+                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
+            }
+
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                    return;
+                }
+                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+            }
+            ty::Predicate::Projection(ref data) => {
+                let trait_ref = data.to_poly_trait_ref(self.tcx);
+                let self_ty = trait_ref.self_ty();
+                if predicate.references_error() {
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                err
+            }
+
+            _ => {
+                if self.tcx.sess.has_errors() {
+                    return;
+                }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot resolve `{}`",
+                    predicate,
+                );
+                err.span_label(span, &format!("cannot resolve `{}`", predicate));
+                err
+            }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
+    }
+
+    /// Returns `true` if the trait predicate may apply for *some* assignment
+    /// to the type parameters.
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool {
+        struct ParamToVarFolder<'a, 'tcx> {
+            infcx: &'a InferCtxt<'a, 'tcx>,
+            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        }
+
+        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
+            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+                self.infcx.tcx
+            }
+
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
+                    let infcx = self.infcx;
+                    self.var_map.entry(ty).or_insert_with(|| {
+                        infcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
+                            span: DUMMY_SP,
+                        })
+                    })
+                } else {
+                    ty.super_fold_with(self)
+                }
+            }
+        }
+
+        self.probe(|_| {
+            let mut selcx = SelectionContext::new(self);
+
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+
+            let cleaned_pred = super::project::normalize(
+                &mut selcx,
+                param_env,
+                ObligationCause::dummy(),
+                &cleaned_pred,
+            )
+            .value;
+
+            let obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                cleaned_pred.without_const().to_predicate(),
+            );
+
+            self.predicate_may_hold(&obligation)
+        })
+    }
+
+    fn note_obligation_cause(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        // First, attempt to add note to this error with an async-await-specific
+        // message, and fall back to regular note otherwise.
+        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            self.note_obligation_cause_code(
+                err,
+                &obligation.predicate,
+                &obligation.cause.code,
+                &mut vec![],
+            );
+        }
+    }
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool {
+        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+
+            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+/// Summarizes information
+#[derive(Clone)]
+pub enum ArgKind {
+    /// An argument of non-tuple type. Parameters are (name, ty)
+    Arg(String, String),
+
+    /// An argument of tuple type. For a "found" argument, the span is
+    /// the locationo in the source of the pattern. For a "expected"
+    /// argument, it will be None. The vector is a list of (name, ty)
+    /// strings for the components of the tuple.
+    Tuple(Option<Span>, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+
+    /// Creates an `ArgKind` from the expected type of an
+    /// argument. It has no name (`_`) and an optional source span.
+    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
+        match t.kind {
+            ty::Tuple(ref tys) => ArgKind::Tuple(
+                span,
+                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
+            ),
+            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
+        }
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+) -> bool {
+    let restrict_msg = "consider further restricting this bound";
+    if let Some(param) =
+        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
+    {
+        if param_name.starts_with("impl ") {
+            // `impl Trait` in argument:
+            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+            err.span_suggestion(
+                param.span,
+                restrict_msg,
+                // `impl CurrentTrait + MissingTrait`
+                format!("{} + {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
+            // If there are no bounds whatsoever, suggest adding a constraint
+            // to the type parameter:
+            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+            err.span_suggestion(
+                param.span,
+                "consider restricting this bound",
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if !generics.where_clause.predicates.is_empty() {
+            // There is a `where` clause, so suggest expanding it:
+            // `fn foo<T>(t: T) where T: Debug {}` →
+            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+            err.span_suggestion(
+                generics.where_clause.span().unwrap().shrink_to_hi(),
+                &format!("consider further restricting type parameter `{}`", param_name),
+                format!(", {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            // If there is no `where` clause lean towards constraining to the
+            // type parameter:
+            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+            let sp = param.span.with_hi(span.hi());
+            let span = source_map.span_through_char(sp, ':');
+            if sp != param.span && sp != span {
+                // Only suggest if we have high certainty that the span
+                // covers the colon in `foo<T: Trait>`.
+                err.span_suggestion(
+                    span,
+                    restrict_msg,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_label(
+                    param.span,
+                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                );
+            }
+        }
+        return true;
+    }
+    false
+}
diff --git a/src/librustc/traits/error_reporting/on_unimplemented.rs b/src/librustc/traits/error_reporting/on_unimplemented.rs
new file mode 100644
index 0000000..2ba12ba
--- /dev/null
+++ b/src/librustc/traits/error_reporting/on_unimplemented.rs
@@ -0,0 +1,213 @@
+use super::{
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
+};
+use crate::infer::InferCtxt;
+use crate::ty::subst::Subst;
+use crate::ty::{self, GenericParamDefKind};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::sym;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    fn impl_similar_to(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Option<DefId> {
+        let tcx = self.tcx;
+        let param_env = obligation.param_env;
+        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
+        let trait_self_ty = trait_ref.self_ty();
+
+        let mut self_match_impls = vec![];
+        let mut fuzzy_match_impls = vec![];
+
+        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
+            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
+            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
+
+            let impl_self_ty = impl_trait_ref.self_ty();
+
+            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
+                self_match_impls.push(def_id);
+
+                if trait_ref
+                    .substs
+                    .types()
+                    .skip(1)
+                    .zip(impl_trait_ref.substs.types().skip(1))
+                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
+                {
+                    fuzzy_match_impls.push(def_id);
+                }
+            }
+        });
+
+        let impl_def_id = if self_match_impls.len() == 1 {
+            self_match_impls[0]
+        } else if fuzzy_match_impls.len() == 1 {
+            fuzzy_match_impls[0]
+        } else {
+            return None;
+        };
+
+        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
+    }
+
+    /// Used to set on_unimplemented's `ItemContext`
+    /// to be the enclosing (async) block/function/closure
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
+        let hir = &self.tcx.hir();
+        let node = hir.find(hir_id)?;
+        match &node {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
+                self.describe_generator(*body_id).or_else(|| {
+                    Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                        "an async function"
+                    } else {
+                        "a function"
+                    })
+                })
+            }
+            hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
+            hir::Node::ImplItem(hir::ImplItem {
+                kind: hir::ImplItemKind::Method(sig, body_id),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| {
+                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                    "an async method"
+                } else {
+                    "a method"
+                })
+            }),
+            hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
+                ..
+            }) => self.describe_generator(*body_id).or_else(|| {
+                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
+            }),
+            hir::Node::Expr(hir::Expr { .. }) => {
+                let parent_hid = hir.get_parent_node(hir_id);
+                if parent_hid != hir_id {
+                    return self.describe_enclosure(parent_hid);
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
+    crate fn on_unimplemented_note(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> OnUnimplementedNote {
+        let def_id =
+            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
+        let trait_ref = *trait_ref.skip_binder();
+
+        let mut flags = vec![];
+        flags.push((
+            sym::item_context,
+            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
+        ));
+
+        match obligation.cause.code {
+            ObligationCauseCode::BuiltinDerivedObligation(..)
+            | ObligationCauseCode::ImplDerivedObligation(..) => {}
+            _ => {
+                // this is a "direct", user-specified, rather than derived,
+                // obligation.
+                flags.push((sym::direct, None));
+            }
+        }
+
+        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
+            // FIXME: maybe also have some way of handling methods
+            // from other traits? That would require name resolution,
+            // which we might want to be some sort of hygienic.
+            //
+            // Currently I'm leaving it for what I need for `try`.
+            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
+                let method = self.tcx.item_name(item);
+                flags.push((sym::from_method, None));
+                flags.push((sym::from_method, Some(method.to_string())));
+            }
+        }
+        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
+            flags.push((sym::parent_trait, Some(t)));
+        }
+
+        if let Some(k) = obligation.cause.span.desugaring_kind() {
+            flags.push((sym::from_desugaring, None));
+            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
+        }
+        let generics = self.tcx.generics_of(def_id);
+        let self_ty = trait_ref.self_ty();
+        // This is also included through the generics list as `Self`,
+        // but the parser won't allow you to use it
+        flags.push((sym::_Self, Some(self_ty.to_string())));
+        if let Some(def) = self_ty.ty_adt_def() {
+            // We also want to be able to select self's original
+            // signature with no type arguments resolved
+            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
+        }
+
+        for param in generics.params.iter() {
+            let value = match param.kind {
+                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                    trait_ref.substs[param.index as usize].to_string()
+                }
+                GenericParamDefKind::Lifetime => continue,
+            };
+            let name = param.name;
+            flags.push((name, Some(value)));
+        }
+
+        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
+            flags.push((sym::crate_local, None));
+        }
+
+        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
+        if self_ty.is_integral() {
+            flags.push((sym::_Self, Some("{integral}".to_owned())));
+        }
+
+        if let ty::Array(aty, len) = self_ty.kind {
+            flags.push((sym::_Self, Some("[]".to_owned())));
+            flags.push((sym::_Self, Some(format!("[{}]", aty))));
+            if let Some(def) = aty.ty_adt_def() {
+                // We also want to be able to select the array's type's original
+                // signature with no type arguments resolved
+                flags.push((
+                    sym::_Self,
+                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
+                ));
+                let tcx = self.tcx;
+                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
+                    ));
+                } else {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
+                    ));
+                }
+            }
+        }
+
+        if let Ok(Some(command)) =
+            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
+        {
+            command.evaluate(self.tcx, trait_ref, &flags[..])
+        } else {
+            OnUnimplementedNote::default()
+        }
+    }
+}
diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs
new file mode 100644
index 0000000..aa5e9f6
--- /dev/null
+++ b/src/librustc/traits/error_reporting/suggestions.rs
@@ -0,0 +1,1745 @@
+use super::{
+    ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
+    PredicateObligation,
+};
+
+use crate::infer::InferCtxt;
+use crate::traits::object_safety::object_safety_violations;
+use crate::ty::TypeckTables;
+use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
+
+use rustc_errors::{
+    error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
+};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::Node;
+use rustc_span::source_map::SourceMap;
+use rustc_span::symbol::{kw, sym};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use std::fmt;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    crate fn suggest_restricting_param_bound(
+        &self,
+        mut err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'_>,
+        body_id: hir::HirId,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (param_ty, projection) = match &self_ty.kind {
+            ty::Param(_) => (true, None),
+            ty::Projection(projection) => (false, Some(projection)),
+            _ => return,
+        };
+
+        let suggest_restriction =
+            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
+                let span = generics.where_clause.span_for_predicates_or_empty_place();
+                if !span.from_expansion() && span.desugaring_kind().is_none() {
+                    err.span_suggestion(
+                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
+                        &format!("consider further restricting {}", msg),
+                        format!(
+                            "{} {} ",
+                            if !generics.where_clause.predicates.is_empty() {
+                                ","
+                            } else {
+                                " where"
+                            },
+                            trait_ref.without_const().to_predicate(),
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            };
+
+        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
+        //        don't suggest `T: Sized + ?Sized`.
+        let mut hir_id = body_id;
+        while let Some(node) = self.tcx.hir().find(hir_id) {
+            match node {
+                hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(..),
+                    ..
+                }) if param_ty && self_ty == self.tcx.types.self_param => {
+                    // Restricting `Self` for a single method.
+                    suggest_restriction(&generics, "`Self`", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
+                | hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(..),
+                    ..
+                })
+                | hir::Node::ImplItem(hir::ImplItem {
+                    generics,
+                    kind: hir::ImplItemKind::Method(..),
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl { generics, .. }, ..
+                }) if projection.is_some() => {
+                    // Missing associated type bound.
+                    suggest_restriction(&generics, "the associated type", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Struct(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Enum(_, generics), span, ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Union(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, ..),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl { generics, .. },
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(_, generics, _),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::TyAlias(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::TraitAlias(generics, _),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
+                    span,
+                    ..
+                })
+                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
+                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
+                    if param_ty =>
+                {
+                    // Missing generic type parameter bound.
+                    let param_name = self_ty.to_string();
+                    let constraint = trait_ref.print_only_trait_path().to_string();
+                    if suggest_constraining_type_param(
+                        generics,
+                        &mut err,
+                        &param_name,
+                        &constraint,
+                        self.tcx.sess.source_map(),
+                        *span,
+                    ) {
+                        return;
+                    }
+                }
+
+                hir::Node::Crate => return,
+
+                _ => {}
+            }
+
+            hir_id = self.tcx.hir().get_parent_item(hir_id);
+        }
+    }
+
+    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
+    /// suggestion to borrow the initializer in order to use have a slice instead.
+    crate fn suggest_borrow_on_unsized_slice(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+    ) {
+        if let &ObligationCauseCode::VariableType(hir_id) = code {
+            let parent_node = self.tcx.hir().get_parent_node(hir_id);
+            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
+                if let Some(ref expr) = local.init {
+                    if let hir::ExprKind::Index(_, _) = expr.kind {
+                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+                            err.span_suggestion(
+                                expr.span,
+                                "consider borrowing here",
+                                format!("&{}", snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// Given a closure's `DefId`, return the given name of the closure.
+    ///
+    /// This doesn't account for reassignments, but it's only used for suggestions.
+    crate fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut DiagnosticBuilder<'_>,
+        msg: &str,
+    ) -> Option<String> {
+        let get_name =
+            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
+                // Get the local name of this closure. This can be inaccurate because
+                // of the possibility of reassignment, but this should be good enough.
+                match &kind {
+                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
+                        Some(format!("{}", name))
+                    }
+                    _ => {
+                        err.note(&msg);
+                        None
+                    }
+                }
+            };
+
+        let hir = self.tcx.hir();
+        let hir_id = hir.as_local_hir_id(def_id)?;
+        let parent_node = hir.get_parent_node(hir_id);
+        match hir.find(parent_node) {
+            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
+                get_name(err, &local.pat.kind)
+            }
+            // Different to previous arm because one is `&hir::Local` and the other
+            // is `P<hir::Local>`.
+            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
+            _ => return None,
+        }
+    }
+
+    /// We tried to apply the bound to an `fn` or closure. 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`.
+    crate fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (def_id, output_ty, callable) = match self_ty.kind {
+            ty::Closure(def_id, substs) => {
+                (def_id, self.closure_sig(def_id, substs).output(), "closure")
+            }
+            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
+            _ => return,
+        };
+        let msg = format!("use parentheses to call the {}", callable);
+
+        let obligation = self.mk_obligation_for_def_id(
+            trait_ref.def_id(),
+            output_ty.skip_binder(),
+            obligation.cause.clone(),
+            obligation.param_env,
+        );
+
+        match self.evaluate_obligation(&obligation) {
+            Ok(EvaluationResult::EvaluatedToOk)
+            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
+            _ => return,
+        }
+        let hir = self.tcx.hir();
+        // Get the name of the callable and the arguments to be used in the suggestion.
+        let snippet = match hir.get_if_local(def_id) {
+            Some(hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
+                ..
+            })) => {
+                err.span_label(*span, "consider calling this closure");
+                let name = match self.get_closure_name(def_id, err, &msg) {
+                    Some(name) => name,
+                    None => return,
+                };
+                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                format!("{}({})", name, args)
+            }
+            Some(hir::Node::Item(hir::Item {
+                ident,
+                kind: hir::ItemKind::Fn(.., body_id),
+                ..
+            })) => {
+                err.span_label(ident.span, "consider calling this function");
+                let body = hir.body(*body_id);
+                let args = body
+                    .params
+                    .iter()
+                    .map(|arg| match &arg.pat.kind {
+                        hir::PatKind::Binding(_, _, ident, None)
+                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
+                        // should suggest a method call.
+                        if ident.name != kw::SelfLower => ident.to_string(),
+                        _ => "_".to_string(),
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                format!("{}({})", ident, args)
+            }
+            _ => return,
+        };
+        if points_at_arg {
+            // When the obligation error has been ensured to have been caused by
+            // an argument, the `obligation.cause.span` points at the expression
+            // of the argument, so we can provide a suggestion. This is signaled
+            // by `points_at_arg`. Otherwise, we give a more general note.
+            err.span_suggestion(
+                obligation.cause.span,
+                &msg,
+                snippet,
+                Applicability::HasPlaceholders,
+            );
+        } else {
+            err.help(&format!("{}: `{}`", msg, snippet));
+        }
+    }
+
+    crate fn suggest_add_reference_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+        has_custom_message: bool,
+    ) -> bool {
+        if !points_at_arg {
+            return false;
+        }
+
+        let span = obligation.cause.span;
+        let param_env = obligation.param_env;
+        let trait_ref = trait_ref.skip_binder();
+
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+            // Try to apply the original trait binding obligation by borrowing.
+            let self_ty = trait_ref.self_ty();
+            let found = self_ty.to_string();
+            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
+            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
+            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
+            let new_obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                new_trait_ref.without_const().to_predicate(),
+            );
+            if self.predicate_must_hold_modulo_regions(&new_obligation) {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    // We have a very specific type of error, where just borrowing this argument
+                    // might solve the problem. In cases like this, the important part is the
+                    // original type obligation, not the last one that failed, which is arbitrary.
+                    // Because of this, we modify the error to refer to the original obligation and
+                    // return early in the caller.
+                    let msg = format!(
+                        "the trait bound `{}: {}` is not satisfied",
+                        found,
+                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                    );
+                    if has_custom_message {
+                        err.note(&msg);
+                    } else {
+                        err.message = vec![(msg, Style::NoStyle)];
+                    }
+                    if snippet.starts_with('&') {
+                        // This is already a literal borrow and the obligation is failing
+                        // somewhere else in the obligation chain. Do not suggest non-sense.
+                        return false;
+                    }
+                    err.span_label(
+                        span,
+                        &format!(
+                            "expected an implementor of trait `{}`",
+                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                        ),
+                    );
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                        Applicability::MaybeIncorrect,
+                    );
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
+    /// 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.
+    crate fn suggest_remove_reference(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let trait_ref = trait_ref.skip_binder();
+        let span = obligation.cause.span;
+
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number =
+                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
+            if let Some('\'') =
+                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
+            {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+
+            let mut trait_type = trait_ref.self_ty();
+
+            for refs_remaining in 0..refs_number {
+                if let ty::Ref(_, t_type, _) = trait_type.kind {
+                    trait_type = t_type;
+
+                    let new_obligation = self.mk_obligation_for_def_id(
+                        trait_ref.def_id,
+                        trait_type,
+                        ObligationCause::dummy(),
+                        obligation.param_env,
+                    );
+
+                    if self.predicate_may_hold(&new_obligation) {
+                        let sp = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+
+                        let remove_refs = refs_remaining + 1;
+                        let format_str =
+                            format!("consider removing {} leading `&`-references", remove_refs);
+
+                        err.span_suggestion_short(
+                            sp,
+                            &format_str,
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                        break;
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    /// Check if the trait bound is implemented for a different mutability and note it in the
+    /// final error.
+    crate fn suggest_change_mut(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let span = obligation.cause.span;
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number =
+                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
+            if let Some('\'') =
+                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
+            {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+            let trait_ref = self.resolve_vars_if_possible(trait_ref);
+            if trait_ref.has_infer_types() {
+                // Do not ICE while trying to find if a reborrow would succeed on a trait with
+                // unresolved bindings.
+                return;
+            }
+
+            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
+                let trait_type = match mutability {
+                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
+                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
+                };
+
+                let new_obligation = self.mk_obligation_for_def_id(
+                    trait_ref.skip_binder().def_id,
+                    trait_type,
+                    ObligationCause::dummy(),
+                    obligation.param_env,
+                );
+
+                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
+                {
+                    let sp = self
+                        .tcx
+                        .sess
+                        .source_map()
+                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
+                        err.span_suggestion(
+                            sp,
+                            "consider changing this borrow's mutability",
+                            "&mut ".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.note(&format!(
+                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
+                            trait_ref.print_only_trait_path(),
+                            trait_type,
+                            trait_ref.skip_binder().self_ty(),
+                        ));
+                    }
+                }
+            }
+        }
+    }
+
+    crate fn suggest_semicolon_removal(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id), ..
+        })) = node
+        {
+            let body = hir.body(*body_id);
+            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
+                if sig.decl.output.span().overlaps(span)
+                    && blk.expr.is_none()
+                    && "()" == &trait_ref.self_ty().to_string()
+                {
+                    // FIXME(estebank): When encountering a method with a trait
+                    // bound not satisfied in the return type with a body that has
+                    // no return, suggest removal of semicolon on last statement.
+                    // Once that is added, close #54771.
+                    if let Some(ref stmt) = blk.stmts.last() {
+                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
+                        err.span_label(sp, "consider removing this semicolon");
+                    }
+                }
+            }
+        }
+    }
+
+    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
+    /// applicable and signal that the error has been expanded appropriately and needs to be
+    /// emitted.
+    crate fn suggest_impl_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) -> bool {
+        match obligation.cause.code.peel_derives() {
+            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return false,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id),
+            ..
+        })) = node
+        {
+            (sig, body_id)
+        } else {
+            return false;
+        };
+        let body = hir.body(*body_id);
+        let trait_ref = self.resolve_vars_if_possible(trait_ref);
+        let ty = trait_ref.skip_binder().self_ty();
+        let is_object_safe = match ty.kind {
+            ty::Dynamic(predicates, _) => {
+                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
+                predicates
+                    .principal_def_id()
+                    .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
+            }
+            // We only want to suggest `impl Trait` to `dyn Trait`s.
+            // For example, `fn foo() -> str` needs to be filtered out.
+            _ => return false,
+        };
+
+        let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
+            ret_ty
+        } else {
+            return false;
+        };
+
+        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
+        // cases like `fn foo() -> (dyn Trait, i32) {}`.
+        // Recursively look for `TraitObject` types and if there's only one, use that span to
+        // suggest `impl Trait`.
+
+        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
+        // otherwise suggest using `Box<dyn Trait>` or an enum.
+        let mut visitor = ReturnsVisitor(vec![]);
+        visitor.visit_body(&body);
+
+        let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+
+        let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id));
+        let (last_ty, all_returns_have_same_type) =
+            ret_types.clone().fold((None, true), |(last_ty, mut same), returned_ty| {
+                same &= last_ty.map_or(true, |ty| ty == returned_ty);
+                (Some(returned_ty), same)
+            });
+        let all_returns_conform_to_trait =
+            if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
+                match ty_ret_ty.kind {
+                    ty::Dynamic(predicates, _) => {
+                        let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
+                        let param_env = ty::ParamEnv::empty();
+                        ret_types.all(|returned_ty| {
+                            predicates.iter().all(|predicate| {
+                                let pred = predicate.with_self_ty(self.tcx, returned_ty);
+                                let obl = Obligation::new(cause.clone(), param_env, pred);
+                                self.predicate_may_hold(&obl)
+                            })
+                        })
+                    }
+                    _ => true,
+                }
+            } else {
+                true
+            };
+
+        let (snippet, last_ty) =
+            if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
+                // Verify that we're dealing with a return `dyn Trait`
+                ret_ty.span.overlaps(span),
+                &ret_ty.kind,
+                self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
+                // If any of the return types does not conform to the trait, then we can't
+                // suggest `impl Trait` nor trait objects, it is a type mismatch error.
+                all_returns_conform_to_trait,
+                last_ty,
+            ) {
+                (snippet, last_ty)
+            } else {
+                return false;
+            };
+        err.code(error_code!(E0746));
+        err.set_primary_message("return type cannot have an unboxed trait object");
+        err.children.clear();
+        let impl_trait_msg = "for information on `impl Trait`, see \
+            <https://doc.rust-lang.org/book/ch10-02-traits.html\
+            #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+            #using-trait-objects-that-allow-for-values-of-different-types>";
+        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
+        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
+        if all_returns_have_same_type {
+            // Suggest `-> impl Trait`.
+            err.span_suggestion(
+                ret_ty.span,
+                &format!(
+                    "return `impl {1}` instead, as all return paths are of type `{}`, \
+                        which implements `{1}`",
+                    last_ty, trait_obj,
+                ),
+                format!("impl {}", trait_obj),
+                Applicability::MachineApplicable,
+            );
+            err.note(impl_trait_msg);
+        } else {
+            if is_object_safe {
+                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
+                // Get all the return values and collect their span and suggestion.
+                let mut suggestions = visitor
+                    .0
+                    .iter()
+                    .map(|expr| {
+                        (
+                            expr.span,
+                            format!(
+                                "Box::new({})",
+                                self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
+                            ),
+                        )
+                    })
+                    .collect::<Vec<_>>();
+                // Add the suggestion for the return type.
+                suggestions.push((
+                    ret_ty.span,
+                    format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
+                ));
+                err.multipart_suggestion(
+                    "return a boxed trait object instead",
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                // This is currently not possible to trigger because E0038 takes precedence, but
+                // leave it in for completeness in case anything changes in an earlier stage.
+                err.note(&format!(
+                    "if trait `{}` was object safe, you could return a trait object",
+                    trait_obj,
+                ));
+            }
+            err.note(trait_obj_msg);
+            err.note(&format!(
+                "if all the returned values were of the same type you could use \
+                    `impl {}` as the return type",
+                trait_obj,
+            ));
+            err.note(impl_trait_msg);
+            err.note("you can create a new `enum` with a variant for each returned type");
+        }
+        true
+    }
+
+    crate fn point_at_returns_when_relevant(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        match obligation.cause.code.peel_derives() {
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
+            node
+        {
+            let body = hir.body(*body_id);
+            // Point at all the `return`s in the function as they have failed trait bounds.
+            let mut visitor = ReturnsVisitor(vec![]);
+            visitor.visit_body(&body);
+            let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+            for expr in &visitor.0 {
+                if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
+                    let ty = self.resolve_vars_if_possible(&returned_ty);
+                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
+                }
+            }
+        }
+    }
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
+        match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                self.tcx
+                    .hir()
+                    .body(id)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+                            *arg.pat
+                        {
+                            ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        let snippet = self
+                                            .tcx
+                                            .sess
+                                            .source_map()
+                                            .span_to_snippet(pat.span)
+                                            .unwrap();
+                                        (snippet, "_".to_owned())
+                                    })
+                                    .collect::<Vec<_>>(),
+                            )
+                        } else {
+                            let name =
+                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
+                            ArgKind::Arg(name, "_".to_owned())
+                        }
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem {
+                span,
+                kind: hir::ImplItemKind::Method(ref sig, _),
+                ..
+            })
+            | Node::TraitItem(&hir::TraitItem {
+                span,
+                kind: hir::TraitItemKind::Method(ref sig, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.clone().kind {
+                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data
+                    .ctor_hir_id()
+                    .map(|hir_id| self.tcx.hir().span(hir_id))
+                    .unwrap_or(DUMMY_SP);
+                let span = self.tcx.sess.source_map().def_span(span);
+
+                (span, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {:?}", node),
+        }
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    pub fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {}", found_str));
+
+            // move |_| { ... }
+            // ^^^^^^^^-- def_span
+            //
+            // move |_| { ... }
+            // ^^^^^-- prefix
+            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
+            // move |_| { ... }
+            //      ^^^-- pipe_span
+            let pipe_span =
+                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion(
+                    pipe_span,
+                    &format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        if expected_args.len() < 2 { "" } else { "s" }
+                    ),
+                    format!("|{}|", underscores),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{}|", sugg),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+                if fields.len() == found_args.len() && is_closure {
+                    let sugg = format!(
+                        "|({}){}|",
+                        found_args
+                            .iter()
+                            .map(|arg| match arg {
+                                ArgKind::Arg(name, _) => name.to_owned(),
+                                _ => "_".to_owned(),
+                            })
+                            .collect::<Vec<String>>()
+                            .join(", "),
+                        // add type annotations if available
+                        if found_args.iter().any(|arg| match arg {
+                            ArgKind::Arg(_, ty) => ty != "_",
+                            _ => false,
+                        }) {
+                            format!(
+                                ": ({})",
+                                fields
+                                    .iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            )
+                        } else {
+                            String::new()
+                        },
+                    );
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to accept a tuple instead of individual arguments",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+        }
+
+        err
+    }
+
+    crate fn report_closure_arg_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_ref: ty::PolyTraitRef<'tcx>,
+        found: ty::PolyTraitRef<'tcx>,
+    ) -> DiagnosticBuilder<'tcx> {
+        crate fn build_fn_sig_string<'tcx>(
+            tcx: TyCtxt<'tcx>,
+            trait_ref: &ty::TraitRef<'tcx>,
+        ) -> String {
+            let inputs = trait_ref.substs.type_at(1);
+            let sig = if let ty::Tuple(inputs) = inputs.kind {
+                tcx.mk_fn_sig(
+                    inputs.iter().map(|k| k.expect_ty()),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            } else {
+                tcx.mk_fn_sig(
+                    ::std::iter::once(inputs),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            };
+            ty::Binder::bind(sig).to_string()
+        }
+
+        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0631,
+            "type mismatch in {} arguments",
+            if argument_is_closure { "closure" } else { "function" }
+        );
+
+        let found_str = format!(
+            "expected signature of `{}`",
+            build_fn_sig_string(self.tcx, found.skip_binder())
+        );
+        err.span_label(span, found_str);
+
+        let found_span = found_span.unwrap_or(span);
+        let expected_str = format!(
+            "found signature of `{}`",
+            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
+        );
+        err.span_label(found_span, expected_str);
+
+        err
+    }
+}
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    crate fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    ) {
+        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
+                err.note(&format!(
+                    "{}s cannot be accessed directly on a `trait`, they can only be \
+                        accessed through a specific `impl`",
+                    assoc_item.kind.suggestion_descr(),
+                ));
+                err.span_suggestion(
+                    span,
+                    "use the fully qualified path to an implementation",
+                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
+                    Applicability::HasPlaceholders,
+                );
+            }
+        }
+    }
+
+    /// Adds an async-await specific note to the diagnostic when the future does not implement
+    /// an auto trait because of a captured type.
+    ///
+    /// ```ignore (diagnostic)
+    /// note: future does not implement `Qux` as this value is used across an await
+    ///   --> $DIR/issue-64130-3-other.rs:17:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
+    /// is "replaced" with a different message and a more specific error.
+    ///
+    /// ```ignore (diagnostic)
+    /// error: future cannot be sent between threads safely
+    ///   --> $DIR/issue-64130-2-send.rs:21:5
+    ///    |
+    /// LL | fn is_send<T: Send>(t: T) { }
+    ///    |    -------    ---- required by this bound in `is_send`
+    /// ...
+    /// LL |     is_send(bar());
+    ///    |     ^^^^^^^ future returned by `bar` is not send
+    ///    |
+    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
+    ///            implemented for `Foo`
+    /// note: future is not send as this value is used across an await
+    ///   --> $DIR/issue-64130-2-send.rs:15:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// Returns `true` if an async-await specific note was added to the diagnostic.
+    crate fn maybe_note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
+                obligation.cause.span={:?}",
+            obligation.predicate, obligation.cause.span
+        );
+        let source_map = self.tcx.sess.source_map();
+
+        // Attempt to detect an async-await error by looking at the obligation causes, looking
+        // for a generator to be present.
+        //
+        // When a future does not implement a trait because of a captured type in one of the
+        // generators somewhere in the call stack, then the result is a chain of obligations.
+        //
+        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
+        // future is passed as an argument to a function C which requires a `Send` type, then the
+        // chain looks something like this:
+        //
+        // - `BuiltinDerivedObligation` with a generator witness (B)
+        // - `BuiltinDerivedObligation` with a generator (B)
+        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
+        // - `BuiltinDerivedObligation` with a generator witness (A)
+        // - `BuiltinDerivedObligation` with a generator (A)
+        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
+        // - `BindingObligation` with `impl_send (Send requirement)
+        //
+        // The first obligation in the chain is the most useful and has the generator that captured
+        // the type. The last generator has information about where the bound was introduced. At
+        // least one generator should be present for this diagnostic to be modified.
+        let (mut trait_ref, mut target_ty) = match obligation.predicate {
+            ty::Predicate::Trait(p, _) => {
+                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
+            }
+            _ => (None, None),
+        };
+        let mut generator = None;
+        let mut last_generator = None;
+        let mut next_code = Some(&obligation.cause.code);
+        while let Some(code) = next_code {
+            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
+            match code {
+                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
+                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
+                    let ty = derived_obligation.parent_trait_ref.self_ty();
+                    debug!(
+                        "maybe_note_obligation_cause_for_async_await: \
+                            parent_trait_ref={:?} self_ty.kind={:?}",
+                        derived_obligation.parent_trait_ref, ty.kind
+                    );
+
+                    match ty.kind {
+                        ty::Generator(did, ..) => {
+                            generator = generator.or(Some(did));
+                            last_generator = Some(did);
+                        }
+                        ty::GeneratorWitness(..) => {}
+                        _ if generator.is_none() => {
+                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
+                            target_ty = Some(ty);
+                        }
+                        _ => {}
+                    }
+
+                    next_code = Some(derived_obligation.parent_code.as_ref());
+                }
+                _ => break,
+            }
+        }
+
+        // Only continue if a generator was found.
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
+                target_ty={:?}",
+            generator, trait_ref, target_ty
+        );
+        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
+            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
+                (generator_did, trait_ref, target_ty)
+            }
+            _ => return false,
+        };
+
+        let span = self.tcx.def_span(generator_did);
+
+        // Do not ICE on closure typeck (#66868).
+        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
+            return false;
+        }
+
+        // Get the tables from the infcx if the generator is the function we are
+        // currently type-checking; otherwise, get them by performing a query.
+        // This is needed to avoid cycles.
+        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
+        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
+             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
+            generator_did,
+            generator_did_root,
+            in_progress_tables.as_ref().map(|t| t.local_id_root),
+            span
+        );
+        let query_tables;
+        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
+            Some(t) if t.local_id_root == Some(generator_did_root) => t,
+            _ => {
+                query_tables = self.tcx.typeck_tables_of(generator_did);
+                &query_tables
+            }
+        };
+
+        // Look for a type inside the generator interior that matches the target type to get
+        // a span.
+        let target_ty_erased = self.tcx.erase_regions(&target_ty);
+        let target_span = tables
+            .generator_interior_types
+            .iter()
+            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
+                // Careful: the regions for types that appear in the
+                // generator interior are not generally known, so we
+                // want to erase them when comparing (and anyway,
+                // `Send` and other bounds are generally unaffected by
+                // the choice of region).  When erasing regions, we
+                // also have to erase late-bound regions. This is
+                // because the types that appear in the generator
+                // interior generally contain "bound regions" to
+                // represent regions that are part of the suspended
+                // generator frame. Bound regions are preserved by
+                // `erase_regions` and so we must also call
+                // `erase_late_bound_regions`.
+                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
+                let ty_erased = self.tcx.erase_regions(&ty_erased);
+                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
+                debug!(
+                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
+                        target_ty_erased={:?} eq={:?}",
+                    ty_erased, target_ty_erased, eq
+                );
+                eq
+            })
+            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
+                (span, source_map.span_to_snippet(*span), scope_span, expr)
+            });
+
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
+                generator_interior_types={:?} target_span={:?}",
+            target_ty, tables.generator_interior_types, target_span
+        );
+        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
+            self.note_obligation_cause_for_async_await(
+                err,
+                *target_span,
+                scope_span,
+                *expr,
+                snippet,
+                generator_did,
+                last_generator,
+                trait_ref,
+                target_ty,
+                tables,
+                obligation,
+                next_code,
+            );
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Unconditionally adds the diagnostic note described in
+    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
+    crate fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    ) {
+        let source_map = self.tcx.sess.source_map();
+
+        let is_async_fn = self
+            .tcx
+            .parent(first_generator)
+            .map(|parent_did| self.tcx.asyncness(parent_did))
+            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
+            .unwrap_or(false);
+        let is_async_move = self
+            .tcx
+            .hir()
+            .as_local_hir_id(first_generator)
+            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
+            .map(|body_id| self.tcx.hir().body(body_id))
+            .and_then(|body| body.generator_kind())
+            .map(|generator_kind| match generator_kind {
+                hir::GeneratorKind::Async(..) => true,
+                _ => false,
+            })
+            .unwrap_or(false);
+        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
+
+        // Special case the primary error message when send or sync is the trait that was
+        // not implemented.
+        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
+        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
+        let hir = self.tcx.hir();
+        let trait_explanation = if is_send || is_sync {
+            let (trait_name, trait_verb) =
+                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
+
+            err.clear_code();
+            err.set_primary_message(format!(
+                "future cannot be {} between threads safely",
+                trait_verb
+            ));
+
+            let original_span = err.span.primary_span().unwrap();
+            let mut span = MultiSpan::from_span(original_span);
+
+            let message = if let Some(name) = last_generator
+                .and_then(|generator_did| self.tcx.parent(generator_did))
+                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
+                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+            {
+                format!("future returned by `{}` is not {}", name, trait_name)
+            } else {
+                format!("future is not {}", trait_name)
+            };
+
+            span.push_span_label(original_span, message);
+            err.set_span(span);
+
+            format!("is not {}", trait_name)
+        } else {
+            format!("does not implement `{}`", trait_ref.print_only_trait_path())
+        };
+
+        // Look at the last interior type to get a span for the `.await`.
+        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
+        let mut span = MultiSpan::from_span(await_span);
+        span.push_span_label(
+            await_span,
+            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
+        );
+
+        span.push_span_label(target_span, format!("has type `{}`", target_ty));
+
+        // If available, use the scope span to annotate the drop location.
+        if let Some(scope_span) = scope_span {
+            span.push_span_label(
+                source_map.end_point(*scope_span),
+                format!("`{}` is later dropped here", snippet),
+            );
+        }
+
+        err.span_note(
+            span,
+            &format!(
+                "future {} as this value is used across an {}",
+                trait_explanation, await_or_yield,
+            ),
+        );
+
+        if let Some(expr_id) = expr {
+            let expr = hir.expect_expr(expr_id);
+            debug!("target_ty evaluated from {:?}", expr);
+
+            let parent = hir.get_parent_node(expr_id);
+            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
+                let parent_span = hir.span(parent);
+                let parent_did = parent.owner_def_id();
+                // ```rust
+                // impl T {
+                //     fn foo(&self) -> i32 {}
+                // }
+                // T.foo();
+                // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
+                // ```
+                //
+                let is_region_borrow =
+                    tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+
+                // ```rust
+                // struct Foo(*const u8);
+                // bar(Foo(std::ptr::null())).await;
+                //     ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
+                // ```
+                debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
+                let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
+                    Some(DefKind::Fn) | Some(DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
+                    _ => false,
+                };
+
+                if (tables.is_method_call(e) && is_region_borrow)
+                    || is_raw_borrow_inside_fn_like_call
+                {
+                    err.span_help(
+                        parent_span,
+                        "consider moving this into a `let` \
+                        binding to create a shorter lived borrow",
+                    );
+                }
+            }
+        }
+
+        // Add a note for the item obligation that remains - normally a note pointing to the
+        // bound that introduced the obligation (e.g. `T: Send`).
+        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
+        self.note_obligation_cause_code(
+            err,
+            &obligation.predicate,
+            next_code.unwrap(),
+            &mut Vec::new(),
+        );
+    }
+
+    crate fn note_obligation_cause_code<T>(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        predicate: &T,
+        cause_code: &ObligationCauseCode<'tcx>,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+    ) where
+        T: fmt::Display,
+    {
+        let tcx = self.tcx;
+        match *cause_code {
+            ObligationCauseCode::ExprAssignable
+            | ObligationCauseCode::MatchExpressionArm { .. }
+            | ObligationCauseCode::Pattern { .. }
+            | ObligationCauseCode::IfExpression { .. }
+            | ObligationCauseCode::IfExpressionWithNoElse
+            | ObligationCauseCode::MainFunctionType
+            | ObligationCauseCode::StartFunctionType
+            | ObligationCauseCode::IntrinsicType
+            | ObligationCauseCode::MethodReceiver
+            | ObligationCauseCode::ReturnNoExpression
+            | ObligationCauseCode::MiscObligation => {}
+            ObligationCauseCode::SliceOrArrayElem => {
+                err.note("slice and array elements must have `Sized` type");
+            }
+            ObligationCauseCode::TupleElem => {
+                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,));
+            }
+            ObligationCauseCode::ReferenceOutlivesReferent(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,
+                ));
+            }
+            ObligationCauseCode::ItemObligation(item_def_id) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by `{}`", item_name);
+
+                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
+                    let sp = tcx.sess.source_map().def_span(sp);
+                    err.span_label(sp, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::BindingObligation(item_def_id, span) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by this bound in `{}`", item_name);
+                if let Some(ident) = tcx.opt_item_name(item_def_id) {
+                    err.span_label(ident.span, "");
+                }
+                if span != DUMMY_SP {
+                    err.span_label(span, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::ObjectCastObligation(object_ty) => {
+                err.note(&format!(
+                    "required for the cast to the object type `{}`",
+                    self.ty_to_string(object_ty)
+                ));
+            }
+            ObligationCauseCode::Coercion { source: _, target } => {
+                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
+            }
+            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
+                err.note(
+                    "the `Copy` trait is required because the repeated element will be copied",
+                );
+                if suggest_const_in_array_repeat_expressions {
+                    err.note(
+                        "this array initializer can be evaluated at compile-time, for more \
+                         information, see issue \
+                         https://github.com/rust-lang/rust/issues/49147",
+                    );
+                    if tcx.sess.opts.unstable_features.is_nightly_build() {
+                        err.help(
+                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
+                             crate attributes to enable",
+                        );
+                    }
+                }
+            }
+            ObligationCauseCode::VariableType(_) => {
+                err.note("all local variables must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedArgumentType => {
+                err.note("all function arguments must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedReturnType => {
+                err.note("the return type of a function must have a statically known size");
+            }
+            ObligationCauseCode::SizedYieldType => {
+                err.note("the yield type of a generator must have a statically known size");
+            }
+            ObligationCauseCode::AssignmentLhsSized => {
+                err.note("the left-hand-side of an assignment must have a statically known size");
+            }
+            ObligationCauseCode::TupleInitializerSized => {
+                err.note("tuples must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::StructInitializerSized => {
+                err.note("structs must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
+                AdtKind::Struct => {
+                    if last {
+                        err.note(
+                            "the last field of a packed struct may only have a \
+                             dynamically sized type if it does not need drop to be run",
+                        );
+                    } else {
+                        err.note(
+                            "only the last field of a struct may have a dynamically sized type",
+                        );
+                    }
+                }
+                AdtKind::Union => {
+                    err.note("no field of a union may have a dynamically sized type");
+                }
+                AdtKind::Enum => {
+                    err.note("no field of an enum variant may have a dynamically sized type");
+                }
+            },
+            ObligationCauseCode::ConstSized => {
+                err.note("constant expressions must have a statically known size");
+            }
+            ObligationCauseCode::ConstPatternStructural => {
+                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
+            }
+            ObligationCauseCode::SharedStatic => {
+                err.note("shared static variables must have a type that implements `Sync`");
+            }
+            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                let ty = parent_trait_ref.skip_binder().self_ty();
+                err.note(&format!("required because it appears within the type `{}`", ty));
+                obligated_types.push(ty);
+
+                let parent_predicate = parent_trait_ref.without_const().to_predicate();
+                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
+                    self.note_obligation_cause_code(
+                        err,
+                        &parent_predicate,
+                        &data.parent_code,
+                        obligated_types,
+                    );
+                }
+            }
+            ObligationCauseCode::ImplDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                err.note(&format!(
+                    "required because of the requirements on the impl of `{}` for `{}`",
+                    parent_trait_ref.print_only_trait_path(),
+                    parent_trait_ref.skip_binder().self_ty()
+                ));
+                let parent_predicate = parent_trait_ref.without_const().to_predicate();
+                self.note_obligation_cause_code(
+                    err,
+                    &parent_predicate,
+                    &data.parent_code,
+                    obligated_types,
+                );
+            }
+            ObligationCauseCode::CompareImplMethodObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the impl method \
+                     but not on the corresponding trait method",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::CompareImplTypeObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the associated impl type \
+                     but not on the corresponding associated trait type",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::ReturnType
+            | ObligationCauseCode::ReturnValue(_)
+            | ObligationCauseCode::BlockTailExpression(_) => (),
+            ObligationCauseCode::TrivialBound => {
+                err.help("see issue #48214");
+                if tcx.sess.opts.unstable_features.is_nightly_build() {
+                    err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
+                }
+            }
+            ObligationCauseCode::AssocTypeBound(ref data) => {
+                err.span_label(data.original, "associated type defined here");
+                if let Some(sp) = data.impl_span {
+                    err.span_label(sp, "in this `impl` item");
+                }
+                for sp in &data.bounds {
+                    err.span_label(*sp, "restricted in this bound");
+                }
+            }
+        }
+    }
+
+    crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
+        let current_limit = self.tcx.sess.recursion_limit.get();
+        let suggested_limit = current_limit * 2;
+        err.help(&format!(
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+            suggested_limit
+        ));
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+) -> bool {
+    let restrict_msg = "consider further restricting this bound";
+    if let Some(param) =
+        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
+    {
+        if param_name.starts_with("impl ") {
+            // `impl Trait` in argument:
+            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+            err.span_suggestion(
+                param.span,
+                restrict_msg,
+                // `impl CurrentTrait + MissingTrait`
+                format!("{} + {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
+            // If there are no bounds whatsoever, suggest adding a constraint
+            // to the type parameter:
+            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+            err.span_suggestion(
+                param.span,
+                "consider restricting this bound",
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if !generics.where_clause.predicates.is_empty() {
+            // There is a `where` clause, so suggest expanding it:
+            // `fn foo<T>(t: T) where T: Debug {}` →
+            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+            err.span_suggestion(
+                generics.where_clause.span().unwrap().shrink_to_hi(),
+                &format!("consider further restricting type parameter `{}`", param_name),
+                format!(", {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            // If there is no `where` clause lean towards constraining to the
+            // type parameter:
+            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+            let sp = param.span.with_hi(span.hi());
+            let span = source_map.span_through_char(sp, ':');
+            if sp != param.span && sp != span {
+                // Only suggest if we have high certainty that the span
+                // covers the colon in `foo<T: Trait>`.
+                err.span_suggestion(
+                    span,
+                    restrict_msg,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_label(
+                    param.span,
+                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                );
+            }
+        }
+        return true;
+    }
+    false
+}
+
+/// Collect all the returned expressions within the input expression.
+/// Used to point at the return spans when we want to suggest some change to them.
+struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>);
+
+impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
+    type Map = rustc::hir::map::Map<'v>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+
+    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        if let hir::ExprKind::Ret(Some(ex)) = ex.kind {
+            self.0.push(ex);
+        }
+        hir::intravisit::walk_expr(self, ex);
+    }
+
+    fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+        if body.generator_kind().is_none() {
+            if let hir::ExprKind::Block(block, None) = body.value.kind {
+                if let Some(expr) = block.expr {
+                    self.0.push(expr);
+                }
+            }
+        }
+        hir::intravisit::walk_body(self, body);
+    }
+}
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index b0b6994..0aac6fb 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -311,7 +311,7 @@
         }
 
         match obligation.predicate {
-            ty::Predicate::Trait(ref data) => {
+            ty::Predicate::Trait(ref data, _) => {
                 let trait_obligation = obligation.with(data.clone());
 
                 if data.is_global() {
@@ -515,6 +515,7 @@
                             obligation.param_env,
                             def_id,
                             substs,
+                            None,
                             Some(obligation.cause.span),
                         ) {
                             Ok(_) => ProcessResult::Changed(vec![]),
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 2d3160d..daaba95 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -29,7 +29,7 @@
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::subst::{InternalSubsts, SubstsRef};
-use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness};
 use crate::util::common::ErrorReported;
 use chalk_engine;
 use rustc_hir as hir;
@@ -155,8 +155,8 @@
     pub code: ObligationCauseCode<'tcx>,
 }
 
-impl<'tcx> ObligationCause<'tcx> {
-    pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
+impl ObligationCause<'_> {
+    pub fn span(&self, tcx: TyCtxt<'_>) -> Span {
         match self.code {
             ObligationCauseCode::CompareImplMethodObligation { .. }
             | ObligationCauseCode::MainFunctionType
@@ -732,7 +732,7 @@
         param_env,
         cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
         recursion_depth: 0,
-        predicate: trait_ref.to_predicate(),
+        predicate: trait_ref.without_const().to_predicate(),
     };
 
     let result = infcx.predicate_must_hold_modulo_regions(&obligation);
@@ -1014,7 +1014,7 @@
 /// environment. If this returns false, then either normalize
 /// encountered an error or one of the predicates did not hold. Used
 /// when creating vtables to check for unsatisfiable methods.
-fn normalize_and_test_predicates<'tcx>(
+pub fn normalize_and_test_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     predicates: Vec<ty::Predicate<'tcx>>,
 ) -> bool {
@@ -1167,6 +1167,17 @@
     }
 }
 
+impl ObligationCauseCode<'_> {
+    // Return the base obligation, ignoring derived obligations.
+    pub fn peel_derives(&self) -> &Self {
+        let mut base_cause = self;
+        while let BuiltinDerivedObligation(cause) | ImplDerivedObligation(cause) = base_cause {
+            base_cause = &cause.parent_code;
+        }
+        base_cause
+    }
+}
+
 impl<'tcx, N> Vtable<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index bfbcb04..15f81bb 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -10,17 +10,18 @@
 
 use super::elaborate_predicates;
 
-use crate::lint;
 use crate::traits::{self, Obligation, ObligationCause};
 use crate::ty::subst::{InternalSubsts, Subst};
-use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
+use syntax::ast;
+
 use std::borrow::Cow;
 use std::iter::{self};
-use syntax::ast::{self};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObjectSafetyViolation {
@@ -178,16 +179,17 @@
             {
                 // 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.
-                tcx.lint_node_note(
-                    lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
+                tcx.struct_span_lint_hir(
+                    WHERE_CLAUSES_OBJECT_SAFETY,
                     hir::CRATE_HIR_ID,
                     *span,
                     &format!(
                         "the trait `{}` cannot be made into an object",
                         tcx.def_path_str(trait_def_id)
                     ),
-                    &violation.error_msg(),
-                );
+                )
+                .note(&violation.error_msg())
+                .emit();
                 false
             } else {
                 true
@@ -232,7 +234,7 @@
         .map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref))
         .any(|predicate| {
             match predicate {
-                ty::Predicate::Trait(ref data) => {
+                ty::Predicate::Trait(ref data, _) => {
                     // In the case of a trait predicate, we can skip the "self" type.
                     data.skip_binder().input_types().skip(1).any(has_self_ty)
                 }
@@ -283,7 +285,7 @@
     let predicates = tcx.predicates_of(def_id);
     let predicates = predicates.instantiate_identity(tcx).predicates;
     elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
-        ty::Predicate::Trait(ref trait_pred) => {
+        ty::Predicate::Trait(ref trait_pred, _) => {
             trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
         }
         ty::Predicate::Projection(..)
@@ -583,6 +585,7 @@
             def_id: unsize_did,
             substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
         }
+        .without_const()
         .to_predicate();
 
         // U: Trait<Arg1, ..., ArgN>
@@ -596,7 +599,7 @@
                     }
                 });
 
-            ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
+            ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
         };
 
         let caller_bounds: Vec<Predicate<'tcx>> = param_env
@@ -618,6 +621,7 @@
             def_id: dispatch_from_dyn_did,
             substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
         }
+        .without_const()
         .to_predicate();
 
         Obligation::new(ObligationCause::dummy(), param_env, predicate)
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 92984b4..669ec5c 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -2,15 +2,15 @@
 
 use crate::ty::{self, GenericParamDefKind, TyCtxt};
 use crate::util::common::ErrorReported;
+
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 use syntax::ast::{MetaItem, NestedMetaItem};
 use syntax::attr;
 
-use rustc_error_codes::*;
-
 #[derive(Clone, Debug)]
 pub struct OnUnimplementedFormatString(Symbol);
 
@@ -292,26 +292,28 @@
                         match generics.params.iter().find(|param| param.name == s) {
                             Some(_) => (),
                             None => {
-                                span_err!(
+                                struct_span_err!(
                                     tcx.sess,
                                     span,
                                     E0230,
                                     "there is no parameter `{}` on trait `{}`",
                                     s,
                                     name
-                                );
+                                )
+                                .emit();
                                 result = Err(ErrorReported);
                             }
                         }
                     }
                     // `{:1}` and `{}` are not to be used
                     Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0231,
                             "only named substitution parameters are allowed"
-                        );
+                        )
+                        .emit();
                         result = Err(ErrorReported);
                     }
                 },
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 79e1b64..62672a7 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -16,8 +16,7 @@
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
 use crate::ty::subst::{InternalSubsts, Subst};
-use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
-use crate::util::common::FN_OUTPUT_NAME;
+use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
@@ -739,7 +738,12 @@
     depth: usize,
 ) -> PredicateObligation<'tcx> {
     let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() }
+    Obligation {
+        cause,
+        recursion_depth: depth,
+        param_env,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
 }
 
 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
@@ -773,7 +777,7 @@
         cause,
         recursion_depth: depth,
         param_env,
-        predicate: trait_ref.to_predicate(),
+        predicate: trait_ref.without_const().to_predicate(),
     };
     let tcx = selcx.infcx().tcx;
     let def_id = projection_ty.item_def_id;
@@ -1364,7 +1368,7 @@
         projection_ty: ty::ProjectionTy::from_ref_and_name(
             tcx,
             trait_ref,
-            Ident::with_dummy_span(FN_OUTPUT_NAME),
+            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
         ),
         ty: ret_type,
     });
@@ -1468,7 +1472,7 @@
     // cycle error if the specialization graph is currently being built.
     let impl_node = specialization_graph::Node::Impl(impl_def_id);
     for item in impl_node.items(tcx) {
-        if item.kind == ty::AssocKind::Type
+        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
             && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
         {
             return specialization_graph::NodeItem {
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 87f7f67..2e5ef5a 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -6,8 +6,6 @@
 use rustc_span::source_map::Span;
 use std::iter::FromIterator;
 
-use rustc_error_codes::*;
-
 impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Given a type `ty` of some value being dropped, computes a set
     /// of "kinds" (types, regions) that must be outlive the execution
@@ -76,15 +74,15 @@
 impl<'tcx> DropckOutlivesResult<'tcx> {
     pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
         if let Some(overflow_ty) = self.overflows.iter().next() {
-            let mut err = struct_span_err!(
+            rustc_errors::struct_span_err!(
                 tcx.sess,
                 span,
                 E0320,
                 "overflow while adding drop-check rules for {}",
                 ty,
-            );
-            err.note(&format!("overflowed on {}", overflow_ty));
-            err.emit();
+            )
+            .note(&format!("overflowed on {}", overflow_ty))
+            .emit();
         }
     }
 
diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs
index c0a0cbe..15870ec 100644
--- a/src/librustc/traits/query/type_op/prove_predicate.rs
+++ b/src/librustc/traits/query/type_op/prove_predicate.rs
@@ -24,7 +24,7 @@
         // `&T`, accounts for about 60% percentage of the predicates
         // we have to prove. No need to canonicalize and all that for
         // such cases.
-        if let Predicate::Trait(trait_ref) = key.value.predicate {
+        if let Predicate::Trait(trait_ref, _) = key.value.predicate {
             if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
                 if trait_ref.def_id() == sized_def_id {
                     if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 1b1cb1b..ac1ca4d 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -37,7 +37,7 @@
 use crate::ty::fast_reject;
 use crate::ty::relate::TypeRelation;
 use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -51,7 +51,7 @@
 use std::fmt::{self, Display};
 use std::iter;
 use std::rc::Rc;
-use syntax::attr;
+use syntax::{ast, attr};
 
 pub struct SelectionContext<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -102,7 +102,7 @@
 impl IntercrateAmbiguityCause {
     /// Emits notes when the overlap is caused by complex intercrate ambiguities.
     /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint(&self, err: &mut errors::DiagnosticBuilder<'_>) {
+    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
         err.note(&self.intercrate_ambiguity_hint());
     }
 
@@ -718,7 +718,7 @@
         }
 
         match obligation.predicate {
-            ty::Predicate::Trait(ref t) => {
+            ty::Predicate::Trait(ref t, _) => {
                 debug_assert!(!t.has_escaping_bound_vars());
                 let obligation = obligation.with(t.clone());
                 self.evaluate_trait_predicate_recursively(previous_stack, obligation)
@@ -802,8 +802,13 @@
 
             ty::Predicate::ConstEvaluatable(def_id, substs) => {
                 if !(obligation.param_env, substs).has_local_value() {
-                    match self.tcx().const_eval_resolve(obligation.param_env, def_id, substs, None)
-                    {
+                    match self.tcx().const_eval_resolve(
+                        obligation.param_env,
+                        def_id,
+                        substs,
+                        None,
+                        None,
+                    ) {
                         Ok(_) => Ok(EvaluatedToOk),
                         Err(_) => Ok(EvaluatedToErr),
                     }
@@ -940,7 +945,9 @@
             // trait refs. This is important because it's only a cycle
             // if the regions match exactly.
             let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
-            let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
+            let cycle = cycle.map(|stack| {
+                ty::Predicate::Trait(stack.obligation.predicate, ast::Constness::NotConst)
+            });
             if self.coinductive_match(cycle) {
                 debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
                 Some(EvaluatedToOk)
@@ -1055,7 +1062,7 @@
 
     fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
         let result = match predicate {
-            ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()),
+            ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
             _ => false,
         };
         debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
@@ -1412,6 +1419,8 @@
 
         debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
 
+        let needs_infer = stack.obligation.predicate.needs_infer();
+
         // If there are STILL multiple candidates, we can further
         // reduce the list by dropping duplicates -- including
         // resolving specializations.
@@ -1419,7 +1428,11 @@
             let mut i = 0;
             while i < candidates.len() {
                 let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
-                    self.candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j])
+                    self.candidate_should_be_dropped_in_favor_of(
+                        &candidates[i],
+                        &candidates[j],
+                        needs_infer,
+                    )
                 });
                 if is_dup {
                     debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
@@ -2253,6 +2266,7 @@
         &mut self,
         victim: &EvaluatedCandidate<'tcx>,
         other: &EvaluatedCandidate<'tcx>,
+        needs_infer: bool,
     ) -> bool {
         if victim.candidate == other.candidate {
             return true;
@@ -2334,10 +2348,55 @@
                     match victim.candidate {
                         ImplCandidate(victim_def) => {
                             let tcx = self.tcx();
-                            return tcx.specializes((other_def, victim_def))
-                                || tcx
-                                    .impls_are_allowed_to_overlap(other_def, victim_def)
-                                    .is_some();
+                            if tcx.specializes((other_def, victim_def)) {
+                                return true;
+                            }
+                            return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
+                                Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
+                                    // Subtle: If the predicate we are evaluating has inference
+                                    // variables, do *not* allow discarding candidates due to
+                                    // marker trait impls.
+                                    //
+                                    // Without this restriction, we could end up accidentally
+                                    // constrainting inference variables based on an arbitrarily
+                                    // chosen trait impl.
+                                    //
+                                    // Imagine we have the following code:
+                                    //
+                                    // ```rust
+                                    // #[marker] trait MyTrait {}
+                                    // impl MyTrait for u8 {}
+                                    // impl MyTrait for bool {}
+                                    // ```
+                                    //
+                                    // And we are evaluating the predicate `<_#0t as MyTrait>`.
+                                    //
+                                    // During selection, we will end up with one candidate for each
+                                    // impl of `MyTrait`. If we were to discard one impl in favor
+                                    // of the other, we would be left with one candidate, causing
+                                    // us to "successfully" select the predicate, unifying
+                                    // _#0t with (for example) `u8`.
+                                    //
+                                    // However, we have no reason to believe that this unification
+                                    // is correct - we've essentially just picked an arbitrary
+                                    // *possibility* for _#0t, and required that this be the *only*
+                                    // possibility.
+                                    //
+                                    // Eventually, we will either:
+                                    // 1) Unify all inference variables in the predicate through
+                                    // some other means (e.g. type-checking of a function). We will
+                                    // then be in a position to drop marker trait candidates
+                                    // without constraining inference variables (since there are
+                                    // none left to constrin)
+                                    // 2) Be left with some unconstrained inference variables. We
+                                    // will then correctly report an inference error, since the
+                                    // existence of multiple marker trait impls tells us nothing
+                                    // about which one should actually apply.
+                                    !needs_infer
+                                }
+                                Some(_) => true,
+                                None => false,
+                            };
                         }
                         ParamCandidate(ref cand) => {
                             // Prefer the impl to a global where clause candidate.
@@ -3309,7 +3368,7 @@
                     tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
                     tcx.mk_substs_trait(source, &[]),
                 );
-                nested.push(predicate_to_obligation(tr.to_predicate()));
+                nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
 
                 // If the type is `Foo + 'a`, ensure that the type
                 // being cast to `Foo + 'a` outlives `'a`:
@@ -3762,16 +3821,12 @@
         // NOTE(flaper87): As of now, it keeps track of the whole error
         // chain. Ideally, we should have a way to configure this either
         // by using -Z verbose or just a CLI argument.
-        if obligation.recursion_depth >= 0 {
-            let derived_cause = DerivedObligationCause {
-                parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
-                parent_code: Rc::new(obligation.cause.code.clone()),
-            };
-            let derived_code = variant(derived_cause);
-            ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
-        } else {
-            obligation.cause.clone()
-        }
+        let derived_cause = DerivedObligationCause {
+            parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
+            parent_code: Rc::new(obligation.cause.code.clone()),
+        };
+        let derived_code = variant(derived_cause);
+        ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
     }
 }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 520cd3e..e559ea3 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -12,20 +12,19 @@
 pub mod specialization_graph;
 
 use crate::infer::{InferCtxt, InferOk};
-use crate::lint;
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
 use rustc_span::DUMMY_SP;
 
 use super::util::impl_trait_ref_and_oblig;
 use super::{FulfillmentContext, SelectionContext};
 
-use rustc_error_codes::*;
-
 /// Information pertinent to an overlapping impl error.
 #[derive(Debug)]
 pub struct OverlapError {
@@ -341,7 +340,7 @@
                                 unreachable!("converted to hard error above")
                             }
                             FutureCompatOverlapErrorKind::Issue33140 => {
-                                lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS
+                                ORDER_DEPENDENT_TRAIT_OBJECTS
                             }
                         };
                         tcx.struct_span_lint_hir(
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index c176f13..9509b62 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -163,7 +163,7 @@
                         tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
                     {
                         match overlap_kind {
-                            ty::ImplOverlapKind::Permitted => {}
+                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
                             ty::ImplOverlapKind::Issue33140 => {
                                 last_lint = Some(FutureCompatOverlapError {
                                     error: overlap_error(overlap),
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 8355239..f3bd98b 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -1,10 +1,10 @@
-use errors::DiagnosticBuilder;
+use rustc_errors::DiagnosticBuilder;
 use rustc_span::Span;
 use smallvec::SmallVec;
 
 use crate::ty::outlives::Component;
 use crate::ty::subst::{GenericArg, Subst, SubstsRef};
-use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -13,8 +13,8 @@
 
 fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
     match *pred {
-        ty::Predicate::Trait(ref data) => {
-            ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data))
+        ty::Predicate::Trait(ref data, constness) => {
+            ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
         }
 
         ty::Predicate::RegionOutlives(ref data) => {
@@ -99,14 +99,14 @@
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
 ) -> Elaborator<'tcx> {
-    elaborate_predicates(tcx, vec![trait_ref.to_predicate()])
+    elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
 }
 
 pub fn elaborate_trait_refs<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
 ) -> Elaborator<'tcx> {
-    let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect();
+    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
     elaborate_predicates(tcx, predicates)
 }
 
@@ -127,7 +127,7 @@
     fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
         let tcx = self.visited.tcx;
         match *predicate {
-            ty::Predicate::Trait(ref data) => {
+            ty::Predicate::Trait(ref data, _) => {
                 // Get predicates declared on the trait.
                 let predicates = tcx.super_predicates_of(data.def_id());
 
@@ -358,7 +358,7 @@
     fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
         let tcx = self.tcx;
         let trait_ref = item.trait_ref();
-        let pred = trait_ref.to_predicate();
+        let pred = trait_ref.without_const().to_predicate();
 
         debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
 
@@ -370,13 +370,9 @@
 
         // Don't recurse if this trait alias is already on the stack for the DFS search.
         let anon_pred = anonymize_predicate(tcx, &pred);
-        if item
-            .path
-            .iter()
-            .rev()
-            .skip(1)
-            .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred)
-        {
+        if item.path.iter().rev().skip(1).any(|(tr, _)| {
+            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
+        }) {
             return false;
         }
 
@@ -471,7 +467,7 @@
 
     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
         while let Some(pred) = self.base_iterator.next() {
-            if let ty::Predicate::Trait(data) = pred {
+            if let ty::Predicate::Trait(data, _) = pred {
                 return Some(data.to_poly_trait_ref());
             }
         }
@@ -545,7 +541,12 @@
     trait_ref: ty::TraitRef<'tcx>,
     recursion_depth: usize,
 ) -> PredicateObligation<'tcx> {
-    Obligation { cause, param_env, recursion_depth, predicate: trait_ref.to_predicate() }
+    Obligation {
+        cause,
+        param_env,
+        recursion_depth,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
 }
 
 pub fn predicate_for_trait_def(
@@ -651,7 +652,7 @@
     match tcx.hir().as_local_hir_id(node_item_def_id) {
         Some(hir_id) => {
             let item = tcx.hir().expect_item(hir_id);
-            if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.kind {
+            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
                 defaultness.is_default()
             } else {
                 false
diff --git a/src/librustc/traits/wf.rs b/src/librustc/traits/wf.rs
index 551f8fd..a0cb844 100644
--- a/src/librustc/traits/wf.rs
+++ b/src/librustc/traits/wf.rs
@@ -3,7 +3,7 @@
 use crate::middle::lang_items;
 use crate::traits::{self, AssocTypeBoundData};
 use crate::ty::subst::SubstsRef;
-use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, Ident};
@@ -62,7 +62,7 @@
 
     // (*) ok to skip binders, because wf code is prepared for it
     match *predicate {
-        ty::Predicate::Trait(ref t) => {
+        ty::Predicate::Trait(ref t, _) => {
             wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
         }
         ty::Predicate::RegionOutlives(..) => {}
@@ -229,9 +229,9 @@
                         //      |
                         //      = note: expected type `u32`
                         //                 found type `()`
-                        if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) {
+                        if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) {
                             let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
-                            if let Some(impl_item) = impl_items
+                            if let Some(impl_item) = items
                                 .iter()
                                 .filter(|item| item.ident == trait_assoc_item.ident)
                                 .next()
@@ -245,7 +245,7 @@
                             }
                         }
                     }
-                    ty::Predicate::Trait(proj) => {
+                    ty::Predicate::Trait(proj, _) => {
                         // An associated item obligation born out of the `trait` failed to be met.
                         // Point at the `impl` that failed the obligation, the associated item that
                         // needed to meet the obligation, and the definition of that associated item,
@@ -279,14 +279,14 @@
                         //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
                         if let (
                             ty::Projection(ty::ProjectionTy { item_def_id, .. }),
-                            Some(hir::ItemKind::Impl(.., impl_items)),
+                            Some(hir::ItemKind::Impl { items, .. }),
                         ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
                         {
                             if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
                                 .filter(|i| i.def_id == *item_def_id)
                                 .next()
                                 .and_then(|trait_assoc_item| {
-                                    impl_items
+                                    items
                                         .iter()
                                         .filter(|i| i.ident == trait_assoc_item.ident)
                                         .next()
@@ -350,7 +350,7 @@
         self.compute_trait_ref(&trait_ref, Elaborate::None);
 
         if !data.has_escaping_bound_vars() {
-            let predicate = trait_ref.to_predicate();
+            let predicate = trait_ref.without_const().to_predicate();
             let cause = self.cause(traits::ProjectionWf(data));
             self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
         }
@@ -359,7 +359,9 @@
     /// Pushes the obligations required for an array length to be WF
     /// into `self.out`.
     fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
-        if let ty::ConstKind::Unevaluated(def_id, substs) = constant.val {
+        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
+            assert!(promoted.is_none());
+
             let obligations = self.nominal_obligations(def_id, substs);
             self.out.extend(obligations);
 
@@ -376,7 +378,11 @@
                 def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
                 substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
             };
-            self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate()));
+            self.out.push(traits::Obligation::new(
+                cause,
+                self.param_env,
+                trait_ref.without_const().to_predicate(),
+            ));
         }
     }
 
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index ebefb03..db034d1 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -81,6 +81,15 @@
     pub target: Ty<'tcx>,
 }
 
+impl Adjustment<'tcx> {
+    pub fn is_region_borrow(&self) -> bool {
+        match self.kind {
+            Adjust::Borrow(AutoBorrow::Ref(..)) => true,
+            _ => false,
+        }
+    }
+}
+
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum Adjust<'tcx> {
     /// Go from ! to any type.
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index 9b27140..df1602b 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -226,11 +226,11 @@
 where
     D: TyDecoder<'tcx>,
 {
-    let base: mir::PlaceBase<'tcx> = Decodable::decode(decoder)?;
+    let local: mir::Local = Decodable::decode(decoder)?;
     let len = decoder.read_usize()?;
     let projection: &'tcx List<mir::PlaceElem<'tcx>> =
         decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
-    Ok(mir::Place { base, projection })
+    Ok(mir::Place { local, projection })
 }
 
 #[inline]
diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs
deleted file mode 100644
index cc5131c..0000000
--- a/src/librustc/ty/constness.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-use crate::hir::map::blocks::FnLikeNode;
-use crate::ty::query::Providers;
-use crate::ty::TyCtxt;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::Symbol;
-use rustc_target::spec::abi::Abi;
-use syntax::attr;
-
-impl<'tcx> TyCtxt<'tcx> {
-    /// Whether the `def_id` counts as const fn in your current crate, considering all active
-    /// feature gates
-    pub fn is_const_fn(self, def_id: DefId) -> bool {
-        self.is_const_fn_raw(def_id)
-            && match self.is_unstable_const_fn(def_id) {
-                Some(feature_name) => {
-                    // has a `rustc_const_unstable` attribute, check whether the user enabled the
-                    // corresponding feature gate.
-                    self.features()
-                        .declared_lib_features
-                        .iter()
-                        .any(|&(sym, _)| sym == feature_name)
-                }
-                // functions without const stability are either stable user written
-                // const fn or the user is using feature gates and we thus don't
-                // care what they do
-                None => true,
-            }
-    }
-
-    /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
-    pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
-        if self.is_const_fn_raw(def_id) {
-            let const_stab = self.lookup_const_stability(def_id)?;
-            if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
-        } else {
-            None
-        }
-    }
-
-    /// Returns `true` if this function must conform to `min_const_fn`
-    pub fn is_min_const_fn(self, def_id: DefId) -> bool {
-        // Bail out if the signature doesn't contain `const`
-        if !self.is_const_fn_raw(def_id) {
-            return false;
-        }
-
-        if self.features().staged_api {
-            // In order for a libstd function to be considered min_const_fn
-            // it needs to be stable and have no `rustc_const_unstable` attribute.
-            match self.lookup_const_stability(def_id) {
-                // `rustc_const_unstable` functions don't need to conform.
-                Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
-                None => {
-                    if let Some(stab) = self.lookup_stability(def_id) {
-                        if stab.level.is_stable() {
-                            self.sess.span_err(
-                                self.def_span(def_id),
-                                "stable const functions must have either `rustc_const_stable` or \
-                            `rustc_const_unstable` attribute",
-                            );
-                            // While we errored above, because we don't know if we need to conform, we
-                            // err on the "safe" side and require min_const_fn.
-                            true
-                        } else {
-                            // Unstable functions need not conform to min_const_fn.
-                            false
-                        }
-                    } else {
-                        // Internal functions are forced to conform to min_const_fn.
-                        // Annotate the internal function with a const stability attribute if
-                        // you need to use unstable features.
-                        // Note: this is an arbitrary choice that does not affect stability or const
-                        // safety or anything, it just changes whether we need to annotate some
-                        // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
-                        true
-                    }
-                }
-                // Everything else needs to conform, because it would be callable from
-                // other `min_const_fn` functions.
-                _ => true,
-            }
-        } else {
-            // users enabling the `const_fn` feature gate can do what they want
-            !self.features().const_fn
-        }
-    }
-}
-
-pub fn provide(providers: &mut Providers<'_>) {
-    /// Const evaluability whitelist is here to check evaluability at the
-    /// top level beforehand.
-    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
-        match tcx.fn_sig(def_id).abi() {
-            Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
-                Some(tcx.lookup_const_stability(def_id).is_some())
-            }
-            _ => None,
-        }
-    }
-
-    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
-    /// said intrinsic is on the whitelist for being const callable.
-    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        let hir_id = tcx
-            .hir()
-            .as_local_hir_id(def_id)
-            .expect("Non-local call to local provider is_const_fn");
-
-        let node = tcx.hir().get(hir_id);
-
-        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
-            whitelisted
-        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
-            fn_like.constness() == hir::Constness::Const
-        } else if let hir::Node::Ctor(_) = node {
-            true
-        } else {
-            false
-        }
-    }
-
-    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        tcx.is_const_fn(def_id)
-            && match tcx.lookup_const_stability(def_id) {
-                Some(stab) => {
-                    if cfg!(debug_assertions) && stab.promotable {
-                        let sig = tcx.fn_sig(def_id);
-                        assert_eq!(
-                            sig.unsafety(),
-                            hir::Unsafety::Normal,
-                            "don't mark const unsafe fns as promotable",
-                            // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
-                        );
-                    }
-                    stab.promotable
-                }
-                None => false,
-            }
-    }
-
-    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        tcx.is_const_fn(def_id)
-            && tcx
-                .lookup_const_stability(def_id)
-                .map(|stab| stab.allow_const_fn_ptr)
-                .unwrap_or(false)
-    }
-
-    *providers = Providers {
-        is_const_fn_raw,
-        is_promotable_const_fn,
-        const_fn_is_allowed_fn_ptr,
-        ..*providers
-    };
-}
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 17f5b98..a51f0f7 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -8,7 +8,7 @@
 use crate::hir::map::DefPathHash;
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
-use crate::lint::{self, Lint};
+use crate::lint::{struct_lint_level, LintSource};
 use crate::middle;
 use crate::middle::cstore::CrateStoreDyn;
 use crate::middle::cstore::EncodedMetadata;
@@ -20,9 +20,6 @@
 use crate::mir::{
     interpret, BodyAndCache, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
 };
-use crate::session::config::CrateType;
-use crate::session::config::{BorrowckMode, OutputFilenames};
-use crate::session::Session;
 use crate::traits;
 use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals};
 use crate::ty::free_region_map::FreeRegionMap;
@@ -44,23 +41,27 @@
 use crate::ty::{InferConst, ParamConst};
 use crate::ty::{List, TyKind, TyS};
 use crate::util::common::ErrorReported;
+use rustc_data_structures::sync;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE};
 use rustc_hir::{HirId, Node, TraitCandidate};
 use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
+use rustc_session::config::CrateType;
+use rustc_session::config::{BorrowckMode, OutputFilenames};
+use rustc_session::Session;
 
-use arena::SyncDroplessArena;
-use errors::DiagnosticBuilder;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::SelfProfilerRef;
-use rustc_data_structures::sharded::ShardedHashMap;
+use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{
     hash_stable_hashmap, HashStable, StableHasher, StableVec,
 };
 use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
+use rustc_errors::DiagnosticBuilder;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
+use rustc_session::lint::{Level, Lint};
 use rustc_session::node_id::NodeMap;
 use rustc_span::source_map::MultiSpan;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -81,21 +82,11 @@
 use syntax::attr;
 use syntax::expand::allocator::AllocatorKind;
 
-pub struct AllArenas {
-    pub interner: SyncDroplessArena,
-}
-
-impl AllArenas {
-    pub fn new() -> Self {
-        AllArenas { interner: SyncDroplessArena::default() }
-    }
-}
-
 type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
 
 pub struct CtxtInterners<'tcx> {
     /// The arena that types, regions, etc. are allocated from.
-    arena: &'tcx SyncDroplessArena,
+    arena: &'tcx WorkerLocal<Arena<'tcx>>,
 
     /// Specifically use a speedy hash algorithm for these hash sets, since
     /// they're accessed quite often.
@@ -115,7 +106,7 @@
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
-    fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
+    fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
         CtxtInterners {
             arena,
             type_: Default::default(),
@@ -313,8 +304,7 @@
 ///
 /// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for
 /// the scope that contains `x`.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
 pub struct GeneratorInteriorTypeCause<'tcx> {
     /// Type of the captured binding.
     pub ty: Ty<'tcx>,
@@ -322,6 +312,8 @@
     pub span: Span,
     /// Span of the scope of the captured binding.
     pub scope_span: Option<Span>,
+    /// Expr which the type evaluated from.
+    pub expr: Option<hir::HirId>,
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug)]
@@ -434,7 +426,7 @@
     /// entire variable.
     pub upvar_list: ty::UpvarListMap,
 
-    /// Stores the type, span and optional scope span of all types
+    /// Stores the type, expression, span and optional scope span of all types
     /// that are live across the yield of this generator (if a generator).
     pub generator_interior_types: Vec<GeneratorInteriorTypeCause<'tcx>>,
 }
@@ -946,7 +938,11 @@
 
     pub sess: &'tcx Session,
 
-    pub lint_store: Lrc<lint::LintStore>,
+    /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
+    ///
+    /// FIXME(Centril): consider `dyn LintStoreMarker` once
+    /// we can upcast to `Any` for some additional type safety.
+    pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
 
     pub dep_graph: DepGraph,
 
@@ -1115,10 +1111,9 @@
     /// reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
-        lint_store: Lrc<lint::LintStore>,
+        lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         local_providers: ty::query::Providers<'tcx>,
         extern_providers: ty::query::Providers<'tcx>,
-        arenas: &'tcx AllArenas,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         resolutions: ty::ResolverOutputs,
         hir: hir_map::Map<'tcx>,
@@ -1129,7 +1124,7 @@
         let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
             s.fatal(&err);
         });
-        let interners = CtxtInterners::new(&arenas.interner);
+        let interners = CtxtInterners::new(arena);
         let common_types = CommonTypes::new(&interners);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
@@ -1560,11 +1555,11 @@
 }
 
 macro_rules! nop_lift {
-    ($ty:ty => $lifted:ty) => {
+    ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if tcx.interners.arena.in_arena(*self as *const _) {
+                if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
                     Some(unsafe { mem::transmute(*self) })
                 } else {
                     None
@@ -1575,14 +1570,14 @@
 }
 
 macro_rules! nop_list_lift {
-    ($ty:ty => $lifted:ty) => {
+    ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
             type Lifted = &'tcx List<$lifted>;
             fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 if self.is_empty() {
                     return Some(List::empty());
                 }
-                if tcx.interners.arena.in_arena(*self as *const _) {
+                if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
                     Some(unsafe { mem::transmute(*self) })
                 } else {
                     None
@@ -1592,31 +1587,31 @@
     };
 }
 
-nop_lift! {Ty<'a> => Ty<'tcx>}
-nop_lift! {Region<'a> => Region<'tcx>}
-nop_lift! {Goal<'a> => Goal<'tcx>}
-nop_lift! {&'a Const<'a> => &'tcx Const<'tcx>}
+nop_lift! {type_; Ty<'a> => Ty<'tcx>}
+nop_lift! {region; Region<'a> => Region<'tcx>}
+nop_lift! {goal; Goal<'a> => Goal<'tcx>}
+nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
 
-nop_list_lift! {Goal<'a> => Goal<'tcx>}
-nop_list_lift! {Clause<'a> => Clause<'tcx>}
-nop_list_lift! {Ty<'a> => Ty<'tcx>}
-nop_list_lift! {ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
-nop_list_lift! {Predicate<'a> => Predicate<'tcx>}
-nop_list_lift! {CanonicalVarInfo => CanonicalVarInfo}
-nop_list_lift! {ProjectionKind => ProjectionKind}
+nop_list_lift! {goal_list; Goal<'a> => Goal<'tcx>}
+nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
+nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
+nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
+nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
+nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo}
+nop_list_lift! {projs; ProjectionKind => ProjectionKind}
 
 // This is the impl for `&'a InternalSubsts<'a>`.
-nop_list_lift! {GenericArg<'a> => GenericArg<'tcx>}
+nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
 pub mod tls {
     use super::{ptr_eq, GlobalCtxt, TyCtxt};
 
     use crate::dep_graph::TaskDeps;
     use crate::ty::query;
-    use errors::Diagnostic;
     use rustc_data_structures::sync::{self, Lock, Lrc};
     use rustc_data_structures::thin_vec::ThinVec;
     use rustc_data_structures::OnDrop;
+    use rustc_errors::Diagnostic;
     use std::mem;
 
     #[cfg(not(parallel_compiler))]
@@ -1930,6 +1925,11 @@
 }
 impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {}
 
+impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> {
+    fn into_pointer(&self) -> *const () {
+        self.0 as *const _ as *const ()
+    }
+}
 // N.B., an `Interned<Ty>` compares and hashes as a `TyKind`.
 impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> {
     fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool {
@@ -2082,7 +2082,7 @@
         $(impl<'tcx> TyCtxt<'tcx> {
             pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
                 self.interners.$field.intern_ref(v, || {
-                    Interned(List::from_arena(&self.interners.arena, v))
+                    Interned(List::from_arena(&*self.arena, v))
                 }).0
             }
         })+
@@ -2434,7 +2434,7 @@
         let mut projection = place.projection.to_vec();
         projection.push(elem);
 
-        Place { base: place.base, projection: self.intern_place_elems(&projection) }
+        Place { local: place.local, projection: self.intern_place_elems(&projection) }
     }
 
     pub fn intern_existential_predicates(
@@ -2551,57 +2551,29 @@
         iter.intern_with(|xs| self.intern_goals(xs))
     }
 
-    pub fn lint_hir<S: Into<MultiSpan>>(
+    pub fn lint_hir(
         self,
         lint: &'static Lint,
         hir_id: HirId,
-        span: S,
+        span: impl Into<MultiSpan>,
         msg: &str,
     ) {
         self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit()
     }
 
-    pub fn lint_hir_note<S: Into<MultiSpan>>(
-        self,
-        lint: &'static Lint,
-        hir_id: HirId,
-        span: S,
-        msg: &str,
-        note: &str,
-    ) {
-        let mut err = self.struct_span_lint_hir(lint, hir_id, span.into(), msg);
-        err.note(note);
-        err.emit()
-    }
-
-    pub fn lint_node_note<S: Into<MultiSpan>>(
-        self,
-        lint: &'static Lint,
-        id: hir::HirId,
-        span: S,
-        msg: &str,
-        note: &str,
-    ) {
-        let mut err = self.struct_span_lint_hir(lint, id, span.into(), msg);
-        err.note(note);
-        err.emit()
-    }
-
     /// Walks upwards from `id` to find a node which might change lint levels with attributes.
     /// It stops at `bound` and just returns it if reached.
-    pub fn maybe_lint_level_root_bounded(
-        self,
-        mut id: hir::HirId,
-        bound: hir::HirId,
-    ) -> hir::HirId {
+    pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
+        let hir = self.hir();
         loop {
             if id == bound {
                 return bound;
             }
-            if lint::maybe_lint_level_root(self, id) {
+
+            if hir.attrs(id).iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some()) {
                 return id;
             }
-            let next = self.hir().get_parent_node(id);
+            let next = hir.get_parent_node(id);
             if next == id {
                 bug!("lint traversal reached the root of the crate");
             }
@@ -2613,7 +2585,7 @@
         self,
         lint: &'static Lint,
         mut id: hir::HirId,
-    ) -> (lint::Level, lint::LintSource) {
+    ) -> (Level, LintSource) {
         let sets = self.lint_levels(LOCAL_CRATE);
         loop {
             if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
@@ -2627,15 +2599,15 @@
         }
     }
 
-    pub fn struct_span_lint_hir<S: Into<MultiSpan>>(
+    pub fn struct_span_lint_hir(
         self,
         lint: &'static Lint,
         hir_id: HirId,
-        span: S,
+        span: impl Into<MultiSpan>,
         msg: &str,
     ) -> DiagnosticBuilder<'tcx> {
         let (level, src) = self.lint_level_at_node(lint, hir_id);
-        lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
+        struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
     }
 
     pub fn struct_lint_node(
@@ -2645,7 +2617,7 @@
         msg: &str,
     ) -> DiagnosticBuilder<'tcx> {
         let (level, src) = self.lint_level_at_node(lint, id);
-        lint::struct_lint_level(self.sess, lint, level, src, None, msg)
+        struct_lint_level(self.sess, lint, level, src, None, msg)
     }
 
     pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx StableVec<TraitCandidate>> {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 25fc484..217ca0c 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -1,12 +1,10 @@
 use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-
-use errors::{Applicability, DiagnosticBuilder};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast;
-use syntax::errors::pluralize;
 
 use std::borrow::Cow;
 use std::fmt;
@@ -246,9 +244,9 @@
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) => {
                 if let Some(principal) = inner.principal() {
-                    format!("trait `{}`", tcx.def_path_str(principal.def_id())).into()
+                    format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
                 } else {
-                    "trait".into()
+                    "trait object".into()
                 }
             }
             ty::Closure(..) => "closure".into(),
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index b9aa12b..4a4280b 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -219,7 +219,7 @@
     fn add_const(&mut self, c: &ty::Const<'_>) {
         self.add_ty(c.ty);
         match c.val {
-            ty::ConstKind::Unevaluated(_, substs) => {
+            ty::ConstKind::Unevaluated(_, substs, _) => {
                 self.add_substs(substs);
                 self.add_flags(TypeFlags::HAS_PROJECTION);
             }
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index b16db6a..0dddca9 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -150,6 +150,15 @@
     }
 }
 
+impl TypeFoldable<'tcx> for syntax::ast::Constness {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
+        *self
+    }
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
+        false
+    }
+}
+
 /// The `TypeFolder` trait defines the actual *folding*. There is a
 /// method defined for every foldable type. Each of these has a
 /// default implementation that does an "identity" fold. Within each
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 9be50d1..51a18f8 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -4,7 +4,7 @@
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
 use rustc_hir::def::Namespace;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_macros::HashStable;
 use rustc_target::spec::abi::Abi;
 
@@ -91,6 +91,40 @@
         let ty = tcx.type_of(self.def.def_id());
         tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
     }
+
+    /// Finds a crate that contains a monomorphization of this instance that
+    /// can be linked to from the local crate. A return value of `None` means
+    /// no upstream crate provides such an exported monomorphization.
+    ///
+    /// This method already takes into account the global `-Zshare-generics`
+    /// setting, always returning `None` if `share-generics` is off.
+    pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
+        // If we are not in share generics mode, we don't link to upstream
+        // monomorphizations but always instantiate our own internal versions
+        // instead.
+        if !tcx.sess.opts.share_generics() {
+            return None;
+        }
+
+        // If this is an item that is defined in the local crate, no upstream
+        // crate can know about it/provide a monomorphization.
+        if self.def_id().is_local() {
+            return None;
+        }
+
+        // If this a non-generic instance, it cannot be a shared monomorphization.
+        if self.substs.non_erasable_generics().next().is_none() {
+            return None;
+        }
+
+        match self.def {
+            InstanceDef::Item(def_id) => tcx
+                .upstream_monomorphizations_for(def_id)
+                .and_then(|monos| monos.get(&self.substs).cloned()),
+            InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
+            _ => None,
+        }
+    }
 }
 
 impl<'tcx> InstanceDef<'tcx> {
@@ -114,7 +148,12 @@
         tcx.get_attrs(self.def_id())
     }
 
-    pub fn is_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
+    /// Returns `true` if the LLVM version of this instance is unconditionally
+    /// marked with `inline`. This implies that a copy of this instance is
+    /// generated in every codegen unit.
+    /// Note that this is only a hint. See the documentation for
+    /// `generates_cgu_internal_copy` for more information.
+    pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
         use crate::hir::map::DefPathData;
         let def_id = match *self {
             ty::InstanceDef::Item(def_id) => def_id,
@@ -127,8 +166,15 @@
         }
     }
 
-    pub fn requires_local(&self, tcx: TyCtxt<'tcx>) -> bool {
-        if self.is_inline(tcx) {
+    /// Returns `true` if the machine code for this instance is instantiated in
+    /// each codegen unit that references it.
+    /// Note that this is only a hint! The compiler can globally decide to *not*
+    /// do this in order to speed up compilation. CGU-internal copies are
+    /// only exist to enable inlining. If inlining is not performed (e.g. at
+    /// `-Copt-level=0`) then the time for generating them is wasted and it's
+    /// better to create a single copy with external linkage.
+    pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool {
+        if self.requires_inline(tcx) {
             return true;
         }
         if let ty::InstanceDef::DropGlue(..) = *self {
@@ -141,7 +187,12 @@
     }
 
     pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
-        tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+        match *self {
+            InstanceDef::Item(def_id) => {
+                tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+            }
+            _ => false,
+        }
     }
 }
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 4b7304e..acaa4ee 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2507,17 +2507,21 @@
         let extra_args = if sig.abi == RustCall {
             assert!(!sig.c_variadic && extra_args.is_empty());
 
-            match sig.inputs().last().unwrap().kind {
-                ty::Tuple(tupled_arguments) => {
+            if let Some(input) = sig.inputs().last() {
+                if let ty::Tuple(tupled_arguments) = input.kind {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
                     tupled_arguments.iter().map(|k| k.expect_ty()).collect()
-                }
-                _ => {
+                } else {
                     bug!(
                         "argument to function with \"rust-call\" ABI \
-                         is not a tuple"
+                            is not a tuple"
                     );
                 }
+            } else {
+                bug!(
+                    "argument to function with \"rust-call\" ABI \
+                        is not a tuple"
+                );
             }
         } else {
             assert!(sig.c_variadic || extra_args.is_empty());
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 7cca123..e67131b 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -6,6 +6,7 @@
 pub use self::IntVarValue::*;
 pub use self::Variance::*;
 
+use crate::arena::Arena;
 use crate::hir::exports::ExportMap;
 use crate::hir::map as hir_map;
 
@@ -18,7 +19,6 @@
 use crate::mir::interpret::ErrorHandled;
 use crate::mir::GeneratorLayout;
 use crate::mir::ReadOnlyBodyAndCache;
-use crate::session::CrateDisambiguator;
 use crate::session::DataTypeKind;
 use crate::traits::{self, Reveal};
 use crate::ty;
@@ -26,12 +26,10 @@
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::util::{Discr, IntTypeExt};
 use crate::ty::walk::TypeWalker;
-use crate::util::captures::Captures;
-use arena::SyncDroplessArena;
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -54,7 +52,7 @@
 use std::ops::Range;
 use std::slice;
 use std::{mem, ptr};
-use syntax::ast::{self, Ident, Name, NodeId};
+use syntax::ast::{self, Constness, Ident, Name, NodeId};
 use syntax::attr;
 
 pub use self::sty::BoundRegion::*;
@@ -76,7 +74,7 @@
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 
-pub use self::context::{keep_local, tls, AllArenas, FreeRegionInfo, TyCtxt};
+pub use self::context::{keep_local, tls, FreeRegionInfo, TyCtxt};
 pub use self::context::{
     CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
     UserType, UserTypeAnnotationIndex,
@@ -97,7 +95,6 @@
 #[macro_use]
 pub mod codec;
 pub mod _match;
-mod constness;
 mod erase_regions;
 pub mod error;
 pub mod fast_reject;
@@ -607,7 +604,7 @@
 
 impl<T: Copy> List<T> {
     #[inline]
-    fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T> {
+    fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
         assert!(slice.len() != 0);
@@ -620,7 +617,9 @@
 
         let size = offset + slice.len() * mem::size_of::<T>();
 
-        let mem = arena.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
+        let mem = arena
+            .dropless
+            .alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
         unsafe {
             let result = &mut *(mem.as_mut_ptr() as *mut List<T>);
             // Write the length
@@ -809,13 +808,6 @@
 pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
 pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
 
-#[derive(Copy, Clone, TypeFoldable)]
-pub struct ClosureUpvar<'tcx> {
-    pub res: Res,
-    pub span: Span,
-    pub ty: Ty<'tcx>,
-}
-
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub enum IntVarValue {
     IntType(ast::IntTy),
@@ -1076,7 +1068,11 @@
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
     /// would be the type parameters.
-    Trait(PolyTraitPredicate<'tcx>),
+    ///
+    /// A trait predicate will have `Constness::Const` if it originates
+    /// from a bound on a `const fn` without the `?const` opt-out (e.g.,
+    /// `const fn foobar<Foo: Bar>() {}`).
+    Trait(PolyTraitPredicate<'tcx>, Constness),
 
     /// `where 'a: 'b`
     RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
@@ -1199,8 +1195,8 @@
 
         let substs = &trait_ref.skip_binder().substs;
         match *self {
-            Predicate::Trait(ref binder) => {
-                Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs)))
+            Predicate::Trait(ref binder, constness) => {
+                Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs)), constness)
             }
             Predicate::Subtype(ref binder) => {
                 Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs)))
@@ -1344,15 +1340,33 @@
     fn to_predicate(&self) -> Predicate<'tcx>;
 }
 
-impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
     fn to_predicate(&self) -> Predicate<'tcx> {
-        ty::Predicate::Trait(ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() }))
+        ty::Predicate::Trait(
+            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+            self.constness,
+        )
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
     fn to_predicate(&self) -> Predicate<'tcx> {
-        ty::Predicate::Trait(self.to_poly_trait_predicate())
+        ty::Predicate::Trait(
+            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+            self.constness,
+        )
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
+    fn to_predicate(&self) -> Predicate<'tcx> {
+        ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&PolyTraitRef<'tcx>> {
+    fn to_predicate(&self) -> Predicate<'tcx> {
+        ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
     }
 }
 
@@ -1421,7 +1435,7 @@
     /// with depth 0 are bound by the predicate.
     pub fn walk_tys(&'a self) -> impl Iterator<Item = Ty<'tcx>> + 'a {
         match *self {
-            ty::Predicate::Trait(ref data) => {
+            ty::Predicate::Trait(ref data, _) => {
                 WalkTysIter::InputTypes(data.skip_binder().input_types())
             }
             ty::Predicate::Subtype(binder) => {
@@ -1447,7 +1461,7 @@
 
     pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
         match *self {
-            Predicate::Trait(ref t) => Some(t.to_poly_trait_ref()),
+            Predicate::Trait(ref t, _) => Some(t.to_poly_trait_ref()),
             Predicate::Projection(..)
             | Predicate::Subtype(..)
             | Predicate::RegionOutlives(..)
@@ -1708,6 +1722,33 @@
     }
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ConstnessAnd<T> {
+    pub constness: Constness,
+    pub value: T,
+}
+
+// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate()` to ensure that
+// the constness of trait bounds is being propagated correctly.
+pub trait WithConstness: Sized {
+    #[inline]
+    fn with_constness(self, constness: Constness) -> ConstnessAnd<Self> {
+        ConstnessAnd { constness, value: self }
+    }
+
+    #[inline]
+    fn with_const(self) -> ConstnessAnd<Self> {
+        self.with_constness(Constness::Const)
+    }
+
+    #[inline]
+    fn without_const(self) -> ConstnessAnd<Self> {
+        self.with_constness(Constness::NotConst)
+    }
+}
+
+impl<T> WithConstness for T {}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
 pub struct ParamEnvAnd<'tcx, T> {
     pub param_env: ParamEnv<'tcx>,
@@ -2369,7 +2410,7 @@
 
     #[inline]
     pub fn variant_range(&self) -> Range<VariantIdx> {
-        (VariantIdx::new(0)..VariantIdx::new(self.variants.len()))
+        VariantIdx::new(0)..VariantIdx::new(self.variants.len())
     }
 
     /// Computes the discriminant value used by a specific variant.
@@ -2431,70 +2472,6 @@
     pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
         tcx.adt_sized_constraint(self.did).0
     }
-
-    fn sized_constraint_for_ty(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
-        let result = match ty.kind {
-            Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
-            | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
-
-            Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
-                // these are never sized - return the target type
-                vec![ty]
-            }
-
-            Tuple(ref tys) => match tys.last() {
-                None => vec![],
-                Some(ty) => self.sized_constraint_for_ty(tcx, ty.expect_ty()),
-            },
-
-            Adt(adt, substs) => {
-                // recursive case
-                let adt_tys = adt.sized_constraint(tcx);
-                debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
-                adt_tys
-                    .iter()
-                    .map(|ty| ty.subst(tcx, substs))
-                    .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
-                    .collect()
-            }
-
-            Projection(..) | Opaque(..) => {
-                // must calculate explicitly.
-                // FIXME: consider special-casing always-Sized projections
-                vec![ty]
-            }
-
-            UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-
-            Param(..) => {
-                // perf hack: if there is a `T: Sized` bound, then
-                // we know that `T` is Sized and do not need to check
-                // it on the impl.
-
-                let sized_trait = match tcx.lang_items().sized_trait() {
-                    Some(x) => x,
-                    _ => return vec![ty],
-                };
-                let sized_predicate = Binder::dummy(TraitRef {
-                    def_id: sized_trait,
-                    substs: tcx.mk_substs_trait(ty, &[]),
-                })
-                .to_predicate();
-                let predicates = tcx.predicates_of(self.did).predicates;
-                if predicates.iter().any(|(p, _)| *p == sized_predicate) {
-                    vec![]
-                } else {
-                    vec![ty]
-                }
-            }
-
-            Placeholder(..) | Bound(..) | Infer(..) => {
-                bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
-            }
-        };
-        debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
-        result
-    }
 }
 
 impl<'tcx> FieldDef {
@@ -2663,7 +2640,12 @@
 #[derive(Debug, PartialEq, Eq)]
 pub enum ImplOverlapKind {
     /// These impls are always allowed to overlap.
-    Permitted,
+    Permitted {
+        /// Whether or not the impl is permitted due to the trait being
+        /// a marker trait (a trait with #[marker], or a trait with
+        /// no associated items and #![feature(overlapping_marker_traits)] enabled)
+        marker: bool,
+    },
     /// These impls are allowed to overlap, but that raises
     /// an issue #33140 future-compatibility warning.
     ///
@@ -2750,57 +2732,6 @@
         is_associated_item.then(|| self.associated_item(def_id))
     }
 
-    fn associated_item_from_trait_item_ref(
-        self,
-        parent_def_id: DefId,
-        parent_vis: &hir::Visibility<'_>,
-        trait_item_ref: &hir::TraitItemRef,
-    ) -> AssocItem {
-        let def_id = self.hir().local_def_id(trait_item_ref.id.hir_id);
-        let (kind, has_self) = match trait_item_ref.kind {
-            hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
-            hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
-            hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-            hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
-        };
-
-        AssocItem {
-            ident: trait_item_ref.ident,
-            kind,
-            // Visibility of trait items is inherited from their traits.
-            vis: Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, self),
-            defaultness: trait_item_ref.defaultness,
-            def_id,
-            container: TraitContainer(parent_def_id),
-            method_has_self_argument: has_self,
-        }
-    }
-
-    fn associated_item_from_impl_item_ref(
-        self,
-        parent_def_id: DefId,
-        impl_item_ref: &hir::ImplItemRef<'_>,
-    ) -> AssocItem {
-        let def_id = self.hir().local_def_id(impl_item_ref.id.hir_id);
-        let (kind, has_self) = match impl_item_ref.kind {
-            hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
-            hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
-            hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-            hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
-        };
-
-        AssocItem {
-            ident: impl_item_ref.ident,
-            kind,
-            // Visibility of trait impl items doesn't matter.
-            vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, self),
-            defaultness: impl_item_ref.defaultness,
-            def_id,
-            container: ImplContainer(parent_def_id),
-            method_has_self_argument: has_self,
-        }
-    }
-
     pub fn field_index(self, hir_id: hir::HirId, tables: &TypeckTables<'_>) -> usize {
         tables.field_indices().get(hir_id).cloned().expect("no index for a field")
     }
@@ -2834,7 +2765,7 @@
         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);
+            return Some(ImplOverlapKind::Permitted { marker: false });
         }
 
         match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
@@ -2844,7 +2775,7 @@
                     "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)",
                     def_id1, def_id2
                 );
-                return Some(ImplOverlapKind::Permitted);
+                return Some(ImplOverlapKind::Permitted { marker: false });
             }
             (ImplPolarity::Positive, ImplPolarity::Negative)
             | (ImplPolarity::Negative, ImplPolarity::Positive) => {
@@ -2880,7 +2811,7 @@
                 "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)",
                 def_id1, def_id2
             );
-            Some(ImplOverlapKind::Permitted)
+            Some(ImplOverlapKind::Permitted { marker: true })
         } else {
             if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
                 if let Some(self_ty2) = self.issue33140_self_ty(def_id2) {
@@ -3078,105 +3009,9 @@
     }
 }
 
-fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> AssocItem {
-    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let parent_id = tcx.hir().get_parent_item(id);
-    let parent_def_id = tcx.hir().local_def_id(parent_id);
-    let parent_item = tcx.hir().expect_item(parent_id);
-    match parent_item.kind {
-        hir::ItemKind::Impl(.., ref impl_item_refs) => {
-            if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
-                let assoc_item =
-                    tcx.associated_item_from_impl_item_ref(parent_def_id, impl_item_ref);
-                debug_assert_eq!(assoc_item.def_id, def_id);
-                return assoc_item;
-            }
-        }
-
-        hir::ItemKind::Trait(.., ref trait_item_refs) => {
-            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
-                let assoc_item = tcx.associated_item_from_trait_item_ref(
-                    parent_def_id,
-                    &parent_item.vis,
-                    trait_item_ref,
-                );
-                debug_assert_eq!(assoc_item.def_id, def_id);
-                return assoc_item;
-            }
-        }
-
-        _ => {}
-    }
-
-    span_bug!(
-        parent_item.span,
-        "unexpected parent of trait or impl item or item not found: {:?}",
-        parent_item.kind
-    )
-}
-
 #[derive(Clone, HashStable)]
 pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);
 
-/// Calculates the `Sized` constraint.
-///
-/// In fact, there are only a few options for the types in the constraint:
-///     - an obviously-unsized type
-///     - a type parameter or projection whose Sizedness can't be known
-///     - a tuple of type parameters or projections, if there are multiple
-///       such.
-///     - a Error, if a type contained itself. The representability
-///       check should catch this case.
-fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> AdtSizedConstraint<'_> {
-    let def = tcx.adt_def(def_id);
-
-    let result = tcx.mk_type_list(
-        def.variants
-            .iter()
-            .flat_map(|v| v.fields.last())
-            .flat_map(|f| def.sized_constraint_for_ty(tcx, tcx.type_of(f.did))),
-    );
-
-    debug!("adt_sized_constraint: {:?} => {:?}", def, result);
-
-    AdtSizedConstraint(result)
-}
-
-fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
-    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let item = tcx.hir().expect_item(id);
-    match item.kind {
-        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
-            trait_item_refs
-                .iter()
-                .map(|trait_item_ref| trait_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id)),
-        ),
-        hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter(
-            impl_item_refs
-                .iter()
-                .map(|impl_item_ref| impl_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id)),
-        ),
-        hir::ItemKind::TraitAlias(..) => &[],
-        _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
-    }
-}
-
-fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
-    tcx.hir().span_if_local(def_id).unwrap()
-}
-
-/// If the given `DefId` describes an item belonging to a trait,
-/// returns the `DefId` of the trait that the trait item belongs to;
-/// otherwise, returns `None`.
-fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
-    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
-        TraitContainer(def_id) => Some(def_id),
-        ImplContainer(_) => None,
-    })
-}
-
 /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
 pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
     if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
@@ -3189,152 +3024,12 @@
     None
 }
 
-/// See `ParamEnv` struct definition for details.
-fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ParamEnv<'_> {
-    // The param_env of an impl Trait type is its defining function's param_env
-    if let Some(parent) = is_impl_trait_defn(tcx, def_id) {
-        return param_env(tcx, parent);
-    }
-    // Compute the bounds on Self and the type parameters.
-
-    let InstantiatedPredicates { predicates } = tcx.predicates_of(def_id).instantiate_identity(tcx);
-
-    // Finally, we have to normalize the bounds in the environment, in
-    // case they contain any associated type projections. This process
-    // can yield errors if the put in illegal associated types, like
-    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
-    // report these errors right here; this doesn't actually feel
-    // right to me, because constructing the environment feels like a
-    // kind of a "idempotent" action, but I'm not sure where would be
-    // a better place. In practice, we construct environments for
-    // every fn once during type checking, and we'll abort if there
-    // are any errors at that point, so after type checking you can be
-    // sure that this will succeed without errors anyway.
-
-    let unnormalized_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        traits::Reveal::UserFacing,
-        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
-    );
-
-    let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
-        tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
-    });
-    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
-    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
-}
-
-fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.sess.local_crate_disambiguator()
-}
-
-fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.crate_name.clone()
-}
-
-fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.hir().crate_hash
-}
-
-fn instance_def_size_estimate<'tcx>(tcx: TyCtxt<'tcx>, instance_def: InstanceDef<'tcx>) -> usize {
-    match instance_def {
-        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
-            let mir = tcx.instance_mir(instance_def);
-            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
-        }
-        // Estimate the size of other compiler-generated shims to be 1.
-        _ => 1,
-    }
-}
-
-/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
-///
-/// See [`ImplOverlapKind::Issue33140`] for more details.
-fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
-    debug!("issue33140_self_ty({:?})", def_id);
-
-    let trait_ref = tcx
-        .impl_trait_ref(def_id)
-        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
-
-    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
-
-    let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
-        && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
-
-    // Check whether these impls would be ok for a marker trait.
-    if !is_marker_like {
-        debug!("issue33140_self_ty - not marker-like!");
-        return None;
-    }
-
-    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
-    if trait_ref.substs.len() != 1 {
-        debug!("issue33140_self_ty - impl has substs!");
-        return None;
-    }
-
-    let predicates = tcx.predicates_of(def_id);
-    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
-        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
-        return None;
-    }
-
-    let self_ty = trait_ref.self_ty();
-    let self_ty_matches = match self_ty.kind {
-        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
-        _ => false,
-    };
-
-    if self_ty_matches {
-        debug!("issue33140_self_ty - MATCHES!");
-        Some(self_ty)
-    } else {
-        debug!("issue33140_self_ty - non-matching self type");
-        None
-    }
-}
-
-/// Check if a function is async.
-fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
-    let hir_id = tcx
-        .hir()
-        .as_local_hir_id(def_id)
-        .unwrap_or_else(|| bug!("asyncness: expected local `DefId`, got `{:?}`", def_id));
-
-    let node = tcx.hir().get(hir_id);
-
-    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
-        bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
-    });
-
-    fn_like.asyncness()
-}
-
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
     context::provide(providers);
     erase_regions::provide(providers);
     layout::provide(providers);
-    constness::provide(providers);
-    *providers = ty::query::Providers {
-        asyncness,
-        associated_item,
-        associated_item_def_ids,
-        adt_sized_constraint,
-        def_span,
-        param_env,
-        trait_of_item,
-        crate_disambiguator,
-        original_crate_name,
-        crate_hash,
-        trait_impls_of: trait_def::trait_impls_of_provider,
-        instance_def_size_estimate,
-        issue33140_self_ty,
-        ..*providers
-    };
+    *providers =
+        ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers };
 }
 
 /// A map for the local crate mapping each type to a vector of its
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 16d8934..7dd3c8f 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -831,7 +831,11 @@
         Ok(self)
     }
 
-    fn pretty_print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+    fn pretty_print_const(
+        mut self,
+        ct: &'tcx ty::Const<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
         if self.tcx().sess.verbose() {
@@ -839,32 +843,54 @@
             return Ok(self);
         }
 
+        macro_rules! print_underscore {
+            () => {{
+                p!(write("_"));
+                if print_ty {
+                    p!(write(": "), print(ct.ty));
+                }
+            }};
+        }
+
         match (ct.val, &ct.ty.kind) {
             (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
-            (ty::ConstKind::Unevaluated(did, substs), _) => match self.tcx().def_kind(did) {
-                Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => {
-                    p!(print_value_path(did, substs))
-                }
-                _ => {
-                    if did.is_local() {
-                        let span = self.tcx().def_span(did);
-                        if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
-                            p!(write("{}", snip))
-                        } else {
-                            p!(write("_: "), print(ct.ty))
+            (ty::ConstKind::Unevaluated(did, substs, promoted), _) => {
+                if let Some(promoted) = promoted {
+                    p!(print_value_path(did, substs));
+                    p!(write("::{:?}", promoted));
+                } else {
+                    match self.tcx().def_kind(did) {
+                        Some(DefKind::Static)
+                        | Some(DefKind::Const)
+                        | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
+                        _ => {
+                            if did.is_local() {
+                                let span = self.tcx().def_span(did);
+                                if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
+                                {
+                                    p!(write("{}", snip))
+                                } else {
+                                    print_underscore!()
+                                }
+                            } else {
+                                print_underscore!()
+                            }
                         }
-                    } else {
-                        p!(write("_: "), print(ct.ty))
                     }
                 }
-            },
-            (ty::ConstKind::Infer(..), _) => p!(write("_: "), print(ct.ty)),
+            }
+            (ty::ConstKind::Infer(..), _) => print_underscore!(),
             (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
-            (ty::ConstKind::Value(value), _) => return self.pretty_print_const_value(value, ct.ty),
+            (ty::ConstKind::Value(value), _) => {
+                return self.pretty_print_const_value(value, ct.ty, print_ty);
+            }
 
             _ => {
                 // fallback
-                p!(write("{:?} : ", ct.val), print(ct.ty))
+                p!(write("{:?}", ct.val));
+                if print_ty {
+                    p!(write(" : "), print(ct.ty));
+                }
             }
         };
         Ok(self)
@@ -874,6 +900,7 @@
         mut self,
         ct: ConstValue<'tcx>,
         ty: Ty<'tcx>,
+        print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
@@ -980,7 +1007,10 @@
                 };
                 if !printed {
                     // fallback
-                    p!(write("{:?} : ", ct), print(ty))
+                    p!(write("{:?}", ct));
+                    if print_ty {
+                        p!(write(" : "), print(ty));
+                    }
                 }
             }
         };
@@ -1154,7 +1184,7 @@
     }
 
     fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
-        self.pretty_print_const(ct)
+        self.pretty_print_const(ct, true)
     }
 
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
@@ -1783,7 +1813,12 @@
 
     ty::Predicate<'tcx> {
         match *self {
-            ty::Predicate::Trait(ref data) => p!(print(data)),
+            ty::Predicate::Trait(ref data, constness) => {
+                if let ast::Constness::Const = constness {
+                    p!(write("const "));
+                }
+                p!(print(data))
+            }
             ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
             ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
             ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index c77cf8c..dbb6a10 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -2,8 +2,7 @@
 use crate::dep_graph::{DepKind, DepNode};
 use crate::ty::query::plumbing::CycleError;
 use crate::ty::query::queries;
-use crate::ty::query::QueryCache;
-use crate::ty::query::{Query, QueryName};
+use crate::ty::query::{Query, QueryCache};
 use crate::ty::TyCtxt;
 use rustc_data_structures::profiling::ProfileCategory;
 use rustc_hir::def_id::{CrateNum, DefId};
@@ -20,7 +19,7 @@
 // FIXME(eddyb) false positive, the lifetime parameter is used for `Key`/`Value`.
 #[allow(unused_lifetimes)]
 pub trait QueryConfig<'tcx> {
-    const NAME: QueryName;
+    const NAME: &'static str;
     const CATEGORY: ProfileCategory;
 
     type Key: Eq + Hash + Clone + Debug;
diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs
index 8a713e3..c1c88e9 100644
--- a/src/librustc/ty/query/keys.rs
+++ b/src/librustc/ty/query/keys.rs
@@ -52,6 +52,16 @@
     }
 }
 
+impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+
+    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl Key for CrateNum {
     fn query_crate(&self) -> CrateNum {
         *self
@@ -106,6 +116,15 @@
     }
 }
 
+impl<'tcx> Key for SubstsRef<'tcx> {
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
     fn query_crate(&self) -> CrateNum {
         self.0.krate
@@ -142,7 +161,7 @@
     }
 }
 
-impl<'tcx> Key for ty::Const<'tcx> {
+impl<'tcx> Key for &'tcx ty::Const<'tcx> {
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
     }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index b163d23..0f09a08 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -1,7 +1,7 @@
 use crate::dep_graph::{self, DepNode};
 use crate::hir::exports::Export;
 use crate::infer::canonical::{self, Canonical};
-use crate::lint;
+use crate::lint::LintLevelMap;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::cstore::{CrateSource, DepKind, NativeLibraryKind};
 use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLibrary};
@@ -15,6 +15,7 @@
 use crate::mir;
 use crate::mir::interpret::GlobalId;
 use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult};
+use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
 use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use crate::session::CrateDisambiguator;
@@ -81,6 +82,9 @@
 mod on_disk_cache;
 pub use self::on_disk_cache::OnDiskCache;
 
+mod profiling_support;
+pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder};
+
 // 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
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index d01927b..a81fe33 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -7,10 +7,10 @@
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
-use errors::Diagnostic;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
@@ -198,7 +198,7 @@
             // Encode query results.
             let mut query_result_index = EncodedQueryResultIndex::new();
 
-            tcx.sess.time("encode query results", || {
+            tcx.sess.time("encode_query_results", || {
                 let enc = &mut encoder;
                 let qri = &mut query_result_index;
 
@@ -1053,8 +1053,8 @@
     Q: super::config::QueryDescription<'tcx, Value: Encodable>,
     E: 'a + TyEncoder,
 {
-    let desc = &format!("encode_query_results for {}", ::std::any::type_name::<Q>());
-    let _timer = tcx.sess.prof.generic_pass(desc);
+    let desc = &format!("encode_query_results_for_{}", ::std::any::type_name::<Q>());
+    let _timer = tcx.sess.prof.extra_verbose_generic_activity(desc);
 
     let shards = Q::query_cache(tcx).lock_shards();
     assert!(shards.iter().all(|shard| shard.active.is_empty()));
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index e56955b..117a38c 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -9,17 +9,15 @@
 use crate::ty::tls;
 use crate::ty::{self, TyCtxt};
 
-use errors::Diagnostic;
-use errors::DiagnosticBuilder;
-use errors::FatalError;
-use errors::Handler;
-use errors::Level;
 #[cfg(not(parallel_compiler))]
 use rustc_data_structures::cold_path;
 use rustc_data_structures::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::profiling::TimingGuard;
 use rustc_data_structures::sharded::Sharded;
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::Span;
 use std::collections::hash_map::Entry;
@@ -27,8 +25,6 @@
 use std::mem;
 use std::ptr;
 
-use rustc_error_codes::*;
-
 pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> {
     pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
     pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
@@ -86,6 +82,19 @@
     /// for some compile-time benchmarks.
     #[inline(always)]
     pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> {
+        // Handling the `query_blocked_prof_timer` is a bit weird because of the
+        // control flow in this function: Blocking is implemented by
+        // awaiting a running job and, once that is done, entering the loop below
+        // again from the top. In that second iteration we will hit the
+        // cache which provides us with the information we need for
+        // finishing the "query-blocked" event.
+        //
+        // We thus allocate `query_blocked_prof_timer` outside the loop,
+        // initialize it during the first iteration and finish it during the
+        // second iteration.
+        #[cfg(parallel_compiler)]
+        let mut query_blocked_prof_timer: Option<TimingGuard<'_>> = None;
+
         let cache = Q::query_cache(tcx);
         loop {
             // We compute the key's hash once and then use it for both the
@@ -99,7 +108,17 @@
             if let Some((_, value)) =
                 lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key)
             {
-                tcx.prof.query_cache_hit(Q::NAME);
+                if unlikely!(tcx.prof.enabled()) {
+                    tcx.prof.query_cache_hit(value.index.into());
+
+                    #[cfg(parallel_compiler)]
+                    {
+                        if let Some(prof_timer) = query_blocked_prof_timer.take() {
+                            prof_timer.finish_with_query_invocation_id(value.index.into());
+                        }
+                    }
+                }
+
                 let result = (value.value.clone(), value.index);
                 #[cfg(debug_assertions)]
                 {
@@ -108,9 +127,6 @@
                 return TryGetJob::JobCompleted(result);
             }
 
-            #[cfg(parallel_compiler)]
-            let query_blocked_prof_timer;
-
             let job = match lock.active.entry((*key).clone()) {
                 Entry::Occupied(entry) => {
                     match *entry.get() {
@@ -120,7 +136,7 @@
                             // self-profiler.
                             #[cfg(parallel_compiler)]
                             {
-                                query_blocked_prof_timer = tcx.prof.query_blocked(Q::NAME);
+                                query_blocked_prof_timer = Some(tcx.prof.query_blocked());
                             }
 
                             job.clone()
@@ -157,11 +173,6 @@
             {
                 let result = job.r#await(tcx, span);
 
-                // This `drop()` is not strictly necessary as the binding
-                // would go out of scope anyway. But it's good to have an
-                // explicit marker of how far the measurement goes.
-                drop(query_blocked_prof_timer);
-
                 if let Err(cycle) = result {
                     return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle));
                 }
@@ -351,7 +362,7 @@
 
     #[inline(never)]
     pub(super) fn get_query<Q: QueryDescription<'tcx>>(self, span: Span, key: Q::Key) -> Q::Value {
-        debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME.as_str(), key, span);
+        debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
 
         let job = match JobOwner::try_get(self, span, &key) {
             TryGetJob::NotYetStarted(job) => job,
@@ -370,7 +381,7 @@
         }
 
         if Q::ANON {
-            let prof_timer = self.prof.query_provider(Q::NAME);
+            let prof_timer = self.prof.query_provider();
 
             let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
                 self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -378,7 +389,7 @@
                 })
             });
 
-            drop(prof_timer);
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             self.dep_graph.read_index(dep_node_index);
 
@@ -440,8 +451,9 @@
         let result = if Q::cache_on_disk(self, key.clone(), None)
             && self.sess.opts.debugging_opts.incremental_queries
         {
-            let _prof_timer = self.prof.incr_cache_loading(Q::NAME);
+            let prof_timer = self.prof.incr_cache_loading();
             let result = Q::try_load_from_disk(self, prev_dep_node_index);
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
             // We always expect to find a cached result for things that
             // can be forced from `DepNode`.
@@ -461,11 +473,13 @@
         } else {
             // We could not load a result from the on-disk cache, so
             // recompute.
-            let _prof_timer = self.prof.query_provider(Q::NAME);
+            let prof_timer = self.prof.query_provider();
 
             // The dep-graph for this computation is already in-place.
             let result = self.dep_graph.with_ignore(|| Q::compute(self, key));
 
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+
             result
         };
 
@@ -527,7 +541,7 @@
             dep_node
         );
 
-        let prof_timer = self.prof.query_provider(Q::NAME);
+        let prof_timer = self.prof.query_provider();
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
             self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -545,7 +559,7 @@
             })
         });
 
-        drop(prof_timer);
+        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if unlikely!(!diagnostics.is_empty()) {
             if dep_node.kind != crate::dep_graph::DepKind::Null {
@@ -576,17 +590,19 @@
 
         let dep_node = Q::to_dep_node(self, &key);
 
-        if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
-            // A None return from `try_mark_green_and_read` means that this is either
-            // a new dep node or that the dep node has already been marked red.
-            // Either way, we can't call `dep_graph.read()` as we don't have the
-            // DepNodeIndex. We must invoke the query itself. The performance cost
-            // this introduces should be negligible as we'll immediately hit the
-            // in-memory cache, or another query down the line will.
-
-            let _ = self.get_query::<Q>(DUMMY_SP, key);
-        } else {
-            self.prof.query_cache_hit(Q::NAME);
+        match self.dep_graph.try_mark_green_and_read(self, &dep_node) {
+            None => {
+                // A None return from `try_mark_green_and_read` means that this is either
+                // a new dep node or that the dep node has already been marked red.
+                // Either way, we can't call `dep_graph.read()` as we don't have the
+                // DepNodeIndex. We must invoke the query itself. The performance cost
+                // this introduces should be negligible as we'll immediately hit the
+                // in-memory cache, or another query down the line will.
+                let _ = self.get_query::<Q>(DUMMY_SP, key);
+            }
+            Some((_, dep_node_index)) => {
+                self.prof.query_cache_hit(dep_node_index.into());
+            }
         }
     }
 
@@ -818,36 +834,6 @@
         }
 
         #[allow(nonstandard_style)]
-        #[derive(Clone, Copy)]
-        pub enum QueryName {
-            $($name),*
-        }
-
-        impl rustc_data_structures::profiling::QueryName for QueryName {
-            fn discriminant(self) -> std::mem::Discriminant<QueryName> {
-                std::mem::discriminant(&self)
-            }
-
-            fn as_str(self) -> &'static str {
-                QueryName::as_str(&self)
-            }
-        }
-
-        impl QueryName {
-            pub fn register_with_profiler(
-                profiler: &rustc_data_structures::profiling::SelfProfiler,
-            ) {
-                $(profiler.register_query_name(QueryName::$name);)*
-            }
-
-            pub fn as_str(&self) -> &'static str {
-                match self {
-                    $(QueryName::$name => stringify!($name),)*
-                }
-            }
-        }
-
-        #[allow(nonstandard_style)]
         #[derive(Clone, Debug)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
@@ -887,12 +873,6 @@
                     $(Query::$name(key) => key.default_span(tcx),)*
                 }
             }
-
-            pub fn query_name(&self) -> QueryName {
-                match self {
-                    $(Query::$name(_) => QueryName::$name,)*
-                }
-            }
         }
 
         impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> {
@@ -927,7 +907,7 @@
             type Key = $K;
             type Value = $V;
 
-            const NAME: QueryName = QueryName::$name;
+            const NAME: &'static str = stringify!($name);
             const CATEGORY: ProfileCategory = $category;
         }
 
@@ -1039,6 +1019,35 @@
             pub fn $name(self, key: $K) -> $V {
                 self.at(DUMMY_SP).$name(key)
             })*
+
+            /// All self-profiling events generated by the query engine use
+            /// virtual `StringId`s for their `event_id`. This method makes all
+            /// those virtual `StringId`s point to actual strings.
+            ///
+            /// If we are recording only summary data, the ids will point to
+            /// just the query names. If we are recording query keys too, we
+            /// allocate the corresponding strings here.
+            pub fn alloc_self_profile_query_strings(self) {
+                use crate::ty::query::profiling_support::{
+                    alloc_self_profile_query_strings_for_query_cache,
+                    QueryKeyStringCache,
+                };
+
+                if !self.prof.enabled() {
+                    return;
+                }
+
+                let mut string_cache = QueryKeyStringCache::new();
+
+                $({
+                    alloc_self_profile_query_strings_for_query_cache(
+                        self,
+                        stringify!($name),
+                        &self.queries.$name,
+                        &mut string_cache,
+                    );
+                })*
+            }
         }
 
         impl TyCtxtAt<$tcx> {
diff --git a/src/librustc/ty/query/profiling_support.rs b/src/librustc/ty/query/profiling_support.rs
new file mode 100644
index 0000000..79b32ba
--- /dev/null
+++ b/src/librustc/ty/query/profiling_support.rs
@@ -0,0 +1,235 @@
+use crate::hir::map::definitions::DefPathData;
+use crate::ty::context::TyCtxt;
+use crate::ty::query::config::QueryConfig;
+use crate::ty::query::plumbing::QueryCache;
+use measureme::{StringComponent, StringId};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::profiling::SelfProfiler;
+use rustc_data_structures::sharded::Sharded;
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use std::fmt::Debug;
+use std::io::Write;
+
+pub struct QueryKeyStringCache {
+    def_id_cache: FxHashMap<DefId, StringId>,
+}
+
+impl QueryKeyStringCache {
+    pub fn new() -> QueryKeyStringCache {
+        QueryKeyStringCache { def_id_cache: Default::default() }
+    }
+}
+
+pub struct QueryKeyStringBuilder<'p, 'c, 'tcx> {
+    profiler: &'p SelfProfiler,
+    tcx: TyCtxt<'tcx>,
+    string_cache: &'c mut QueryKeyStringCache,
+}
+
+impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+    pub fn new(
+        profiler: &'p SelfProfiler,
+        tcx: TyCtxt<'tcx>,
+        string_cache: &'c mut QueryKeyStringCache,
+    ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+        QueryKeyStringBuilder { profiler, tcx, string_cache }
+    }
+
+    // The current implementation is rather crude. In the future it might be a
+    // good idea to base this on `ty::print` in order to get nicer and more
+    // efficient query keys.
+    fn def_id_to_string_id(&mut self, def_id: DefId) -> StringId {
+        if let Some(&string_id) = self.string_cache.def_id_cache.get(&def_id) {
+            return string_id;
+        }
+
+        let def_key = self.tcx.def_key(def_id);
+
+        let (parent_string_id, start_index) = match def_key.parent {
+            Some(parent_index) => {
+                let parent_def_id = DefId { index: parent_index, krate: def_id.krate };
+
+                (self.def_id_to_string_id(parent_def_id), 0)
+            }
+            None => (StringId::INVALID, 2),
+        };
+
+        let dis_buffer = &mut [0u8; 16];
+        let name;
+        let dis;
+        let end_index;
+
+        match def_key.disambiguated_data.data {
+            DefPathData::CrateRoot => {
+                name = self.tcx.original_crate_name(def_id.krate).as_str();
+                dis = "";
+                end_index = 3;
+            }
+            other => {
+                name = other.as_symbol().as_str();
+                if def_key.disambiguated_data.disambiguator == 0 {
+                    dis = "";
+                    end_index = 3;
+                } else {
+                    write!(&mut dis_buffer[..], "[{}]", def_key.disambiguated_data.disambiguator)
+                        .unwrap();
+                    let end_of_dis = dis_buffer.iter().position(|&c| c == b']').unwrap();
+                    dis = std::str::from_utf8(&dis_buffer[..end_of_dis + 1]).unwrap();
+                    end_index = 4;
+                }
+            }
+        }
+
+        let components = [
+            StringComponent::Ref(parent_string_id),
+            StringComponent::Value("::"),
+            StringComponent::Value(&name[..]),
+            StringComponent::Value(dis),
+        ];
+
+        let string_id = self.profiler.alloc_string(&components[start_index..end_index]);
+
+        self.string_cache.def_id_cache.insert(def_id, string_id);
+
+        string_id
+    }
+}
+
+pub trait IntoSelfProfilingString {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId;
+}
+
+// The default implementation of `IntoSelfProfilingString` just uses `Debug`
+// which is slow and causes lots of duplication of string data.
+// The specialized impls below take care of making the `DefId` case more
+// efficient.
+impl<T: Debug> IntoSelfProfilingString for T {
+    default fn to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        let s = format!("{:?}", self);
+        builder.profiler.alloc_string(&s[..])
+    }
+}
+
+impl IntoSelfProfilingString for DefId {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(*self)
+    }
+}
+
+impl IntoSelfProfilingString for CrateNum {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
+    }
+}
+
+impl IntoSelfProfilingString for DefIndex {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
+    }
+}
+
+impl<T0, T1> IntoSelfProfilingString for (T0, T1)
+where
+    T0: IntoSelfProfilingString + Debug,
+    T1: IntoSelfProfilingString + Debug,
+{
+    default fn to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        let val0 = self.0.to_self_profile_string(builder);
+        let val1 = self.1.to_self_profile_string(builder);
+
+        let components = &[
+            StringComponent::Value("("),
+            StringComponent::Ref(val0),
+            StringComponent::Value(","),
+            StringComponent::Ref(val1),
+            StringComponent::Value(")"),
+        ];
+
+        builder.profiler.alloc_string(components)
+    }
+}
+
+/// Allocate the self-profiling query strings for a single query cache. This
+/// method is called from `alloc_self_profile_query_strings` which knows all
+/// the queries via macro magic.
+pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>(
+    tcx: TyCtxt<'tcx>,
+    query_name: &'static str,
+    query_cache: &Sharded<QueryCache<'tcx, Q>>,
+    string_cache: &mut QueryKeyStringCache,
+) where
+    Q: QueryConfig<'tcx>,
+{
+    tcx.prof.with_profiler(|profiler| {
+        let event_id_builder = profiler.event_id_builder();
+
+        // Walk the entire query cache and allocate the appropriate
+        // string representations. Each cache entry is uniquely
+        // identified by its dep_node_index.
+        if profiler.query_key_recording_enabled() {
+            let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);
+
+            let query_name = profiler.get_or_alloc_cached_string(query_name);
+
+            // Since building the string representation of query keys might
+            // need to invoke queries itself, we cannot keep the query caches
+            // locked while doing so. Instead we copy out the
+            // `(query_key, dep_node_index)` pairs and release the lock again.
+            let query_keys_and_indices = {
+                let shards = query_cache.lock_shards();
+                let len = shards.iter().map(|shard| shard.results.len()).sum();
+
+                let mut query_keys_and_indices = Vec::with_capacity(len);
+
+                for shard in &shards {
+                    query_keys_and_indices.extend(
+                        shard.results.iter().map(|(q_key, q_val)| (q_key.clone(), q_val.index)),
+                    );
+                }
+
+                query_keys_and_indices
+            };
+
+            // Now actually allocate the strings. If allocating the strings
+            // generates new entries in the query cache, we'll miss them but
+            // we don't actually care.
+            for (query_key, dep_node_index) in query_keys_and_indices {
+                // Translate the DepNodeIndex into a QueryInvocationId
+                let query_invocation_id = dep_node_index.into();
+
+                // Create the string version of the query-key
+                let query_key = query_key.to_self_profile_string(&mut query_string_builder);
+                let event_id = event_id_builder.from_label_and_arg(query_name, query_key);
+
+                // Doing this in bulk might be a good idea:
+                profiler.map_query_invocation_id_to_string(
+                    query_invocation_id,
+                    event_id.to_string_id(),
+                );
+            }
+        } else {
+            // In this branch we don't allocate query keys
+            let query_name = profiler.get_or_alloc_cached_string(query_name);
+            let event_id = event_id_builder.from_label(query_name).to_string_id();
+
+            let shards = query_cache.lock_shards();
+
+            for shard in shards.iter() {
+                let query_invocation_ids = shard
+                    .results
+                    .values()
+                    .map(|v| v.index)
+                    .map(|dep_node_index| dep_node_index.into());
+
+                profiler
+                    .bulk_map_query_invocation_id_to_single_string(query_invocation_ids, event_id);
+            }
+        }
+    });
+}
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 9472281..3b9df72 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -568,12 +568,12 @@
 
         // FIXME(const_generics): this is wrong, as it is a projection
         (
-            ty::ConstKind::Unevaluated(a_def_id, a_substs),
-            ty::ConstKind::Unevaluated(b_def_id, b_substs),
-        ) if a_def_id == b_def_id => {
+            ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted),
+            ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted),
+        ) if a_def_id == b_def_id && a_promoted == b_promoted => {
             let substs =
                 relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
-            Ok(ty::ConstKind::Unevaluated(a_def_id, &substs))
+            Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted))
         }
         _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
     };
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index eade515..c1ae4d9 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -15,6 +15,7 @@
 use std::fmt;
 use std::rc::Rc;
 use std::sync::Arc;
+use syntax::ast;
 
 impl fmt::Debug for ty::GenericParamDef {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -45,12 +46,6 @@
     }
 }
 
-impl fmt::Debug for ty::ClosureUpvar<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ClosureUpvar({:?},{:?})", self.res, self.ty)
-    }
-}
-
 impl fmt::Debug for ty::UpvarId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let name = ty::tls::with(|tcx| tcx.hir().name(self.var_path.hir_id));
@@ -240,7 +235,12 @@
 impl fmt::Debug for ty::Predicate<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            ty::Predicate::Trait(ref a) => a.fmt(f),
+            ty::Predicate::Trait(ref a, constness) => {
+                if let ast::Constness::Const = constness {
+                    write!(f, "const ")?;
+                }
+                a.fmt(f)
+            }
             ty::Predicate::Subtype(ref pair) => pair.fmt(f),
             ty::Predicate::RegionOutlives(ref pair) => pair.fmt(f),
             ty::Predicate::TypeOutlives(ref pair) => pair.fmt(f),
@@ -480,7 +480,9 @@
     type Lifted = ty::Predicate<'tcx>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         match *self {
-            ty::Predicate::Trait(ref binder) => tcx.lift(binder).map(ty::Predicate::Trait),
+            ty::Predicate::Trait(ref binder, constness) => {
+                tcx.lift(binder).map(|binder| ty::Predicate::Trait(binder, constness))
+            }
             ty::Predicate::Subtype(ref binder) => tcx.lift(binder).map(ty::Predicate::Subtype),
             ty::Predicate::RegionOutlives(ref binder) => {
                 tcx.lift(binder).map(ty::Predicate::RegionOutlives)
@@ -1030,8 +1032,8 @@
         match *self {
             ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
             ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
-            ty::ConstKind::Unevaluated(did, substs) => {
-                ty::ConstKind::Unevaluated(did, substs.fold_with(folder))
+            ty::ConstKind::Unevaluated(did, substs, promoted) => {
+                ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted)
             }
             ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => {
                 *self
@@ -1043,7 +1045,7 @@
         match *self {
             ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
             ty::ConstKind::Param(p) => p.visit_with(visitor),
-            ty::ConstKind::Unevaluated(_, substs) => substs.visit_with(visitor),
+            ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor),
             ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
                 false
             }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index aeda2eb..837b2fc 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -9,15 +9,17 @@
 use crate::middle::region;
 use crate::mir::interpret::ConstValue;
 use crate::mir::interpret::Scalar;
+use crate::mir::Promoted;
 use crate::ty::layout::VariantIdx;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
-use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable};
+use crate::ty::{
+    self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
+};
 use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS};
-use crate::util::captures::Captures;
+use polonius_engine::Atom;
+use rustc_data_structures::captures::Captures;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-
-use polonius_engine::Atom;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, Symbol};
@@ -527,7 +529,7 @@
     pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
         // FIXME requires optimized MIR
         let num_variants = tcx.generator_layout(def_id).variant_fields.len();
-        (VariantIdx::new(0)..VariantIdx::new(num_variants))
+        VariantIdx::new(0)..VariantIdx::new(num_variants)
     }
 
     /// The discriminant for the given variant. Panics if the `variant_index` is
@@ -665,14 +667,16 @@
     pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
         use crate::ty::ToPredicate;
         match *self.skip_binder() {
-            ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(),
+            ExistentialPredicate::Trait(tr) => {
+                Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate()
+            }
             ExistentialPredicate::Projection(p) => {
                 ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty)))
             }
             ExistentialPredicate::AutoTrait(did) => {
                 let trait_ref =
                     Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
-                trait_ref.to_predicate()
+                trait_ref.without_const().to_predicate()
             }
         }
     }
@@ -2376,7 +2380,7 @@
 
     #[inline]
     pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
-        let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs| {
+        let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| {
             let param_env_and_substs = param_env.with_reveal_all().and(substs);
 
             // Avoid querying `tcx.const_eval(...)` with any e.g. inference vars.
@@ -2388,11 +2392,11 @@
 
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            tcx.const_eval_resolve(param_env, did, substs, None).ok()
+            tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
         };
 
         match self.val {
-            ConstKind::Unevaluated(did, substs) => {
+            ConstKind::Unevaluated(did, substs, promoted) => {
                 // HACK(eddyb) when substs contain e.g. inference variables,
                 // attempt using identity substs instead, that will succeed
                 // when the expression doesn't depend on any parameters.
@@ -2402,12 +2406,12 @@
                     let identity_substs = InternalSubsts::identity_for_item(tcx, did);
                     // The `ParamEnv` needs to match the `identity_substs`.
                     let identity_param_env = tcx.param_env(did);
-                    match try_const_eval(did, identity_param_env, identity_substs) {
+                    match try_const_eval(did, identity_param_env, identity_substs, promoted) {
                         Some(ct) => ct.subst(tcx, substs),
                         None => self,
                     }
                 } else {
-                    try_const_eval(did, param_env, substs).unwrap_or(self)
+                    try_const_eval(did, param_env, substs, promoted).unwrap_or(self)
                 }
             }
             _ => self,
@@ -2471,7 +2475,7 @@
 
     /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
     /// variants when the code is monomorphic enough for that.
-    Unevaluated(DefId, SubstsRef<'tcx>),
+    Unevaluated(DefId, SubstsRef<'tcx>, Option<Promoted>),
 
     /// Used to hold computed value.
     Value(ConstValue<'tcx>),
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index aa93f35..8d22ac9 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -3,18 +3,18 @@
 use crate::hir::map::DefPathData;
 use crate::ich::NodeIdHashingMode;
 use crate::mir::interpret::{sign_extend, truncate};
-use crate::ty::layout::{Integer, IntegerExt};
+use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use crate::ty::TyKind::*;
 use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable};
 use crate::util::common::ErrorReported;
+use rustc_apfloat::Float as _;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_span::Span;
 use std::{cmp, fmt};
@@ -43,26 +43,38 @@
     }
 }
 
+fn signed_min(size: Size) -> i128 {
+    sign_extend(1_u128 << (size.bits() - 1), size) as i128
+}
+
+fn signed_max(size: Size) -> i128 {
+    i128::max_value() >> (128 - size.bits())
+}
+
+fn unsigned_max(size: Size) -> u128 {
+    u128::max_value() >> (128 - size.bits())
+}
+
+fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
+    let (int, signed) = match ty.kind {
+        Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
+        Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
+        _ => bug!("non integer discriminant"),
+    };
+    (int.size(), signed)
+}
+
 impl<'tcx> Discr<'tcx> {
     /// Adds `1` to the value and wraps around if the maximum for the type is reached.
     pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self {
         self.checked_add(tcx, 1).0
     }
     pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
-        let (int, signed) = match self.ty.kind {
-            Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
-            Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
-            _ => bug!("non integer discriminant"),
-        };
-
-        let size = int.size();
-        let bit_size = int.size().bits();
-        let shift = 128 - bit_size;
-        if signed {
-            let sext = |u| sign_extend(u, size) as i128;
-            let min = sext(1_u128 << (bit_size - 1));
-            let max = i128::max_value() >> shift;
-            let val = sext(self.val);
+        let (size, signed) = int_size_and_signed(tcx, self.ty);
+        let (val, oflo) = if signed {
+            let min = signed_min(size);
+            let max = signed_max(size);
+            let val = sign_extend(self.val, size) as i128;
             assert!(n < (i128::max_value() as u128));
             let n = n as i128;
             let oflo = val > max - n;
@@ -70,14 +82,15 @@
             // zero the upper bits
             let val = val as u128;
             let val = truncate(val, size);
-            (Self { val: val as u128, ty: self.ty }, oflo)
+            (val, oflo)
         } else {
-            let max = u128::max_value() >> shift;
+            let max = unsigned_max(size);
             let val = self.val;
             let oflo = val > max - n;
             let val = if oflo { n - (max - val) - 1 } else { val + n };
-            (Self { val: val, ty: self.ty }, oflo)
-        }
+            (val, oflo)
+        };
+        (Self { val, ty: self.ty }, oflo)
     }
 }
 
@@ -533,8 +546,6 @@
 
         if self.is_mutable_static(def_id) {
             self.mk_mut_ptr(static_ty)
-        } else if self.is_foreign_item(def_id) {
-            self.mk_imm_ptr(static_ty)
         } else {
             self.mk_imm_ref(self.lifetimes.re_erased, static_ty)
         }
@@ -623,6 +634,44 @@
 }
 
 impl<'tcx> ty::TyS<'tcx> {
+    /// Returns the maximum value for the given numeric type (including `char`s)
+    /// or returns `None` if the type is not numeric.
+    pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
+        let val = match self.kind {
+            ty::Int(_) | ty::Uint(_) => {
+                let (size, signed) = int_size_and_signed(tcx, self);
+                let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
+                Some(val)
+            }
+            ty::Char => Some(std::char::MAX as u128),
+            ty::Float(fty) => Some(match fty {
+                ast::FloatTy::F32 => ::rustc_apfloat::ieee::Single::INFINITY.to_bits(),
+                ast::FloatTy::F64 => ::rustc_apfloat::ieee::Double::INFINITY.to_bits(),
+            }),
+            _ => None,
+        };
+        val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
+    }
+
+    /// Returns the minimum value for the given numeric type (including `char`s)
+    /// or returns `None` if the type is not numeric.
+    pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
+        let val = match self.kind {
+            ty::Int(_) | ty::Uint(_) => {
+                let (size, signed) = int_size_and_signed(tcx, self);
+                let val = if signed { truncate(signed_min(size) as u128, size) } else { 0 };
+                Some(val)
+            }
+            ty::Char => Some(0),
+            ty::Float(fty) => Some(match fty {
+                ast::FloatTy::F32 => (-::rustc_apfloat::ieee::Single::INFINITY).to_bits(),
+                ast::FloatTy::F64 => (-::rustc_apfloat::ieee::Double::INFINITY).to_bits(),
+            }),
+            _ => None,
+        };
+        val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self)))
+    }
+
     /// Checks whether values of this type `T` are *moved* or *copied*
     /// when referenced -- this amounts to a check for whether `T:
     /// Copy`, but note that we **don't** consider lifetimes when
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index 9e0dd8e..da08fbc 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -81,7 +81,8 @@
         | ty::Bound(..)
         | ty::Foreign(..) => {}
         ty::Array(ty, len) => {
-            if let ty::ConstKind::Unevaluated(_, substs) = len.val {
+            if let ty::ConstKind::Unevaluated(_, substs, promoted) = len.val {
+                assert!(promoted.is_none());
                 stack.extend(substs.types().rev());
             }
             stack.push(len.ty);
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 9574685..19b43bf 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -5,15 +5,10 @@
 use std::fmt::Debug;
 use std::time::{Duration, Instant};
 
-use rustc_span::symbol::{sym, Symbol};
-
 #[cfg(test)]
 mod tests;
 
-// The name of the associated type for `Fn` return types.
-pub const FN_OUTPUT_NAME: Symbol = sym::Output;
-
-pub use errors::ErrorReported;
+pub use rustc_errors::ErrorReported;
 
 pub fn to_readable_str(mut val: usize) -> String {
     let mut groups = vec![];
diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml
deleted file mode 100644
index df117de..0000000
--- a/src/librustc_asan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_asan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_asan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
deleted file mode 100644
index e276dc1..0000000
--- a/src/librustc_asan/build.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-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();
-
-        let (native, target) = match sanitizer_lib_boilerplate("asan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-        native.fixup_sanitizer_lib_name("asan");
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_asan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_ast_lowering/Cargo.toml b/src/librustc_ast_lowering/Cargo.toml
index 408e9a7..4b786d6 100644
--- a/src/librustc_ast_lowering/Cargo.toml
+++ b/src/librustc_ast_lowering/Cargo.toml
@@ -17,7 +17,6 @@
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_session = { path = "../librustc_session" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index 6c8b8b0..5dc855e 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -2,7 +2,7 @@
 
 use rustc::bug;
 use rustc_data_structures::thin_vec::ThinVec;
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
@@ -10,7 +10,6 @@
 use syntax::ast::*;
 use syntax::attr;
 use syntax::ptr::P as AstP;
-use syntax::{span_err, struct_span_err};
 
 impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -202,7 +201,12 @@
             ExprKind::Mac(_) => panic!("Shouldn't exist here"),
         };
 
-        hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: e.span, attrs: e.attrs.clone() }
+        hir::Expr {
+            hir_id: self.lower_node_id(e.id),
+            kind,
+            span: e.span,
+            attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
+        }
     }
 
     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
@@ -685,12 +689,13 @@
         match generator_kind {
             Some(hir::GeneratorKind::Gen) => {
                 if !decl.inputs.is_empty() {
-                    span_err!(
+                    struct_span_err!(
                         self.sess,
                         fn_decl_span,
                         E0628,
                         "generators cannot have explicit parameters"
-                    );
+                    )
+                    .emit();
                 }
                 Some(movability)
             }
@@ -699,7 +704,8 @@
             }
             None => {
                 if movability == Movability::Static {
-                    span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static");
+                    struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static")
+                        .emit();
                 }
                 None
             }
@@ -842,10 +848,7 @@
         }
     }
 
-    fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
         let len = self.catch_scopes.len();
         self.catch_scopes.push(catch_id);
 
@@ -861,10 +864,7 @@
         result
     }
 
-    fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
         // We're no longer in the base loop's condition; we're in another loop.
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
@@ -886,10 +886,7 @@
         result
     }
 
-    fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = true;
 
@@ -902,18 +899,18 @@
 
     fn lower_expr_asm(&mut self, asm: &InlineAsm) -> hir::ExprKind<'hir> {
         let inner = hir::InlineAsmInner {
-            inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
+            inputs: asm.inputs.iter().map(|&(c, _)| c).collect(),
             outputs: asm
                 .outputs
                 .iter()
                 .map(|out| hir::InlineAsmOutput {
-                    constraint: out.constraint.clone(),
+                    constraint: out.constraint,
                     is_rw: out.is_rw,
                     is_indirect: out.is_indirect,
                     span: out.expr.span,
                 })
                 .collect(),
-            asm: asm.asm.clone(),
+            asm: asm.asm,
             asm_str_style: asm.asm_str_style,
             clobbers: asm.clobbers.clone().into(),
             volatile: asm.volatile,
@@ -946,7 +943,13 @@
         match self.generator_kind {
             Some(hir::GeneratorKind::Gen) => {}
             Some(hir::GeneratorKind::Async(_)) => {
-                span_err!(self.sess, span, E0727, "`async` generators are not yet supported",);
+                struct_span_err!(
+                    self.sess,
+                    span,
+                    E0727,
+                    "`async` generators are not yet supported"
+                )
+                .emit();
                 return hir::ExprKind::Err;
             }
             None => self.generator_kind = Some(hir::GeneratorKind::Gen),
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 2515ca9..2025d0c 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -3,7 +3,7 @@
 
 use rustc::arena::Arena;
 use rustc::bug;
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -14,7 +14,6 @@
 use rustc_target::spec::abi;
 use syntax::ast::*;
 use syntax::attr;
-use syntax::struct_span_err;
 use syntax::visit::{self, Visitor};
 
 use log::debug;
@@ -25,19 +24,16 @@
     pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
 }
 
-impl<'a, 'lowering, 'hir> ItemLowerer<'a, 'lowering, 'hir> {
-    fn with_trait_impl_ref<F>(&mut self, trait_impl_ref: &Option<TraitRef>, f: F)
-    where
-        F: FnOnce(&mut Self),
-    {
+impl ItemLowerer<'_, '_, '_> {
+    fn with_trait_impl_ref(&mut self, impl_ref: &Option<TraitRef>, f: impl FnOnce(&mut Self)) {
         let old = self.lctx.is_in_trait_impl;
-        self.lctx.is_in_trait_impl = if let &None = trait_impl_ref { false } else { true };
+        self.lctx.is_in_trait_impl = if let &None = impl_ref { false } else { true };
         f(self);
         self.lctx.is_in_trait_impl = old;
     }
 }
 
-impl<'a, 'lowering, 'hir> Visitor<'a> for ItemLowerer<'a, 'lowering, 'hir> {
+impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
     fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
         let hir_id = self.lctx.lower_node_id(n);
 
@@ -70,8 +66,14 @@
         if let Some(hir_id) = item_hir_id {
             self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
                 let this = &mut ItemLowerer { lctx: this };
-                if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.kind {
-                    this.with_trait_impl_ref(opt_trait_ref, |this| visit::walk_item(this, item));
+                if let ItemKind::Impl { constness, ref of_trait, .. } = item.kind {
+                    if constness == Constness::Const {
+                        this.lctx
+                            .diagnostic()
+                            .span_err(item.span, "const trait impls are not yet implemented");
+                    }
+
+                    this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
                 } else {
                     visit::walk_item(this, item);
                 }
@@ -115,7 +117,7 @@
         let old_len = self.in_scope_lifetimes.len();
 
         let parent_generics = match self.items.get(&parent_hir_id).unwrap().kind {
-            hir::ItemKind::Impl(_, _, _, ref generics, ..)
+            hir::ItemKind::Impl { ref generics, .. }
             | hir::ItemKind::Trait(_, _, ref generics, ..) => &generics.params[..],
             _ => &[],
         };
@@ -170,7 +172,7 @@
                 vec
             }
             ItemKind::MacroDef(..) => SmallVec::new(),
-            ItemKind::Fn(..) | ItemKind::Impl(.., None, _, _) => smallvec![i.id],
+            ItemKind::Fn(..) | ItemKind::Impl { of_trait: None, .. } => smallvec![i.id],
             ItemKind::Static(ref ty, ..) => {
                 let mut ids = smallvec![i.id];
                 if self.sess.features_untracked().impl_trait_in_bindings {
@@ -358,15 +360,16 @@
                     self.lower_generics(generics, ImplTraitContext::disallowed()),
                 )
             }
-            ItemKind::Impl(
+            ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
-                ref ast_generics,
-                ref trait_ref,
-                ref ty,
-                ref impl_items,
-            ) => {
+                constness,
+                generics: ref ast_generics,
+                of_trait: ref trait_ref,
+                self_ty: ref ty,
+                items: ref impl_items,
+            } => {
                 let def_id = self.resolver.definitions().local_def_id(id);
 
                 // Lower the "impl header" first. This ordering is important
@@ -414,15 +417,16 @@
                         )
                     });
 
-                hir::ItemKind::Impl(
+                hir::ItemKind::Impl {
                     unsafety,
                     polarity,
-                    self.lower_defaultness(defaultness, true /* [1] */),
+                    defaultness: self.lower_defaultness(defaultness, true /* [1] */),
+                    constness,
                     generics,
-                    trait_ref,
-                    lowered_ty,
-                    new_impl_items,
-                )
+                    of_trait: trait_ref,
+                    self_ty: lowered_ty,
+                    items: new_impl_items,
+                }
             }
             ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index bc3dfec..284ede3 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 //! Lowers the AST to the HIR.
 //!
 //! Since the AST and HIR are fairly similar, this is mostly a simple procedure,
@@ -33,43 +31,40 @@
 //! in the HIR, especially for multiple identifiers.
 
 #![feature(array_value_iter)]
+#![feature(crate_visibility_modifier)]
 
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::hir::intravisit;
-use rustc::hir::map::{DefKey, DefPathData, Definitions};
-use rustc::lint;
-use rustc::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
-use rustc::middle::cstore::CrateStore;
-use rustc::util::captures::Captures;
-use rustc::util::common::FN_OUTPUT_NAME;
+use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions};
+use rustc::hir::map::Map;
 use rustc::{bug, span_bug};
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use rustc_error_codes::*;
-use rustc_errors::Applicability;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::IndexVec;
 use rustc_session::config::nightly_options;
+use rustc_session::lint::{builtin, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::node_id::NodeMap;
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
-use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind, Spanned};
+use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 use syntax::ast;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::print::pprust;
-use syntax::ptr::P as AstP;
 use syntax::sess::ParseSess;
 use syntax::token::{self, Nonterminal, Token};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::{self, Visitor};
-use syntax::{help, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use log::{debug, trace};
 use smallvec::{smallvec, SmallVec};
@@ -85,6 +80,8 @@
 
 mod expr;
 mod item;
+mod pat;
+mod path;
 
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
@@ -172,7 +169,9 @@
 }
 
 pub trait Resolver {
-    fn cstore(&self) -> &dyn CrateStore;
+    fn def_key(&mut self, id: DefId) -> DefKey;
+
+    fn item_generics_num_lifetimes(&self, def: DefId, sess: &Session) -> usize;
 
     /// Obtains resolution for a `NodeId` with a single resolution.
     fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
@@ -197,7 +196,7 @@
         ns: Namespace,
     ) -> (ast::Path, Res<NodeId>);
 
-    fn lint_buffer(&mut self) -> &mut lint::LintBuffer;
+    fn lint_buffer(&mut self) -> &mut LintBuffer;
 
     fn next_node_id(&mut self) -> NodeId;
 }
@@ -267,7 +266,7 @@
     // incr. comp. yet.
     dep_graph.assert_ignored();
 
-    let _prof_timer = sess.prof.generic_activity("hir_lowering");
+    let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
 
     LoweringContext {
         crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
@@ -432,10 +431,11 @@
                 }
             }
 
-            fn with_hir_id_owner<F, T>(&mut self, owner: Option<NodeId>, f: F) -> T
-            where
-                F: FnOnce(&mut Self) -> T,
-            {
+            fn with_hir_id_owner<T>(
+                &mut self,
+                owner: Option<NodeId>,
+                f: impl FnOnce(&mut Self) -> T,
+            ) -> T {
                 let old = mem::replace(&mut self.hir_id_owner, owner);
                 let r = f(self);
                 self.hir_id_owner = old;
@@ -443,7 +443,7 @@
             }
         }
 
-        impl<'tcx, 'lowering, 'hir> Visitor<'tcx> for MiscCollector<'tcx, 'lowering, 'hir> {
+        impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
             fn visit_pat(&mut self, p: &'tcx Pat) {
                 if let PatKind::Paren(..) | PatKind::Rest = p.kind {
                     // Doesn't generate a HIR node
@@ -576,10 +576,11 @@
         lowered
     }
 
-    fn lower_node_id_generic<F>(&mut self, ast_node_id: NodeId, alloc_hir_id: F) -> hir::HirId
-    where
-        F: FnOnce(&mut Self) -> hir::HirId,
-    {
+    fn lower_node_id_generic(
+        &mut self,
+        ast_node_id: NodeId,
+        alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId,
+    ) -> hir::HirId {
         if ast_node_id == DUMMY_NODE_ID {
             return hir::DUMMY_HIR_ID;
         }
@@ -603,10 +604,7 @@
         }
     }
 
-    fn with_hir_id_owner<F, T>(&mut self, owner: NodeId, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
         let counter = self
             .item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
@@ -735,15 +733,12 @@
     /// Presuming that in-band lifetimes are enabled, then
     /// `self.anonymous_lifetime_mode` will be updated to match the
     /// parameter while `f` is running (and restored afterwards).
-    fn collect_in_band_defs<T, F>(
+    fn collect_in_band_defs<T>(
         &mut self,
         parent_id: DefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
-        f: F,
-    ) -> (Vec<hir::GenericParam<'hir>>, T)
-    where
-        F: FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
-    {
+        f: impl FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
+    ) -> (Vec<hir::GenericParam<'hir>>, T) {
         assert!(!self.is_collecting_in_band_lifetimes);
         assert!(self.lifetimes_to_define.is_empty());
         let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
@@ -846,10 +841,11 @@
     // This is used to track which lifetimes have already been defined, and
     // which are new in-band lifetimes that need to have a definition created
     // for them.
-    fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_in_scope_lifetime_defs<T>(
+        &mut self,
+        params: &[GenericParam],
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
             GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
@@ -869,16 +865,13 @@
     /// Presuming that in-band lifetimes are enabled, then
     /// `self.anonymous_lifetime_mode` will be updated to match the
     /// parameter while `f` is running (and restored afterwards).
-    fn add_in_band_defs<F, T>(
+    fn add_in_band_defs<T>(
         &mut self,
         generics: &Generics,
         parent_id: DefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
-        f: F,
-    ) -> (hir::Generics<'hir>, T)
-    where
-        F: FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
-    {
+        f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
+    ) -> (hir::Generics<'hir>, T) {
         let (in_band_defs, (mut lowered_generics, res)) =
             self.with_in_scope_lifetime_defs(&generics.params, |this| {
                 this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
@@ -916,10 +909,7 @@
         (lowered_generics, res)
     }
 
-    fn with_dyn_type_scope<T, F>(&mut self, in_scope: bool, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_dyn_type = self.is_in_dyn_type;
         self.is_in_dyn_type = in_scope;
 
@@ -930,10 +920,7 @@
         result
     }
 
-    fn with_new_scopes<T, F>(&mut self, f: F) -> T
-    where
-        F: FnOnce(&mut Self) -> T,
-    {
+    fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
@@ -948,14 +935,6 @@
         ret
     }
 
-    fn def_key(&mut self, id: DefId) -> DefKey {
-        if id.is_local() {
-            self.resolver.definitions().def_key(id.index)
-        } else {
-            self.resolver.cstore().def_key(id)
-        }
-    }
-
     fn lower_attrs(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] {
         self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)))
     }
@@ -1270,10 +1249,16 @@
                     let bounds =
                         this.arena.alloc_from_iter(bounds.iter().filter_map(
                             |bound| match *bound {
-                                GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
+                                GenericBound::Trait(ref ty, TraitBoundModifier::None)
+                                | GenericBound::Trait(ref ty, TraitBoundModifier::MaybeConst) => {
                                     Some(this.lower_poly_trait_ref(ty, itctx.reborrow()))
                                 }
-                                GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+                                // `?const ?Bound` will cause an error during AST validation
+                                // anyways, so treat it like `?Bound` as compilation proceeds.
+                                GenericBound::Trait(_, TraitBoundModifier::Maybe)
+                                | GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
+                                    None
+                                }
                                 GenericBound::Outlives(ref lifetime) => {
                                     if lifetime_bound.is_none() {
                                         lifetime_bound = Some(this.lower_lifetime(lifetime));
@@ -1347,10 +1332,9 @@
                         );
                         if pos == ImplTraitPosition::Binding && nightly_options::is_nightly_build()
                         {
-                            help!(
-                                err,
+                            err.help(
                                 "add `#![feature(impl_trait_in_bindings)]` to the crate \
-                                   attributes to enable"
+                                   attributes to enable",
                             );
                         }
                         err.emit();
@@ -1485,7 +1469,9 @@
         }
 
         impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
+            type Map = Map<'v>;
+
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1633,403 +1619,6 @@
         )
     }
 
-    fn lower_qpath(
-        &mut self,
-        id: NodeId,
-        qself: &Option<QSelf>,
-        p: &Path,
-        param_mode: ParamMode,
-        mut itctx: ImplTraitContext<'_, 'hir>,
-    ) -> hir::QPath<'hir> {
-        let qself_position = qself.as_ref().map(|q| q.position);
-        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
-
-        let partial_res =
-            self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
-
-        let proj_start = p.segments.len() - partial_res.unresolved_segments();
-        let path = self.arena.alloc(hir::Path {
-            res: self.lower_res(partial_res.base_res()),
-            segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
-                |(i, segment)| {
-                    let param_mode = match (qself_position, param_mode) {
-                        (Some(j), ParamMode::Optional) if i < j => {
-                            // This segment is part of the trait path in a
-                            // qualified path - one of `a`, `b` or `Trait`
-                            // in `<X as a::b::Trait>::T::U::method`.
-                            ParamMode::Explicit
-                        }
-                        _ => param_mode,
-                    };
-
-                    // Figure out if this is a type/trait segment,
-                    // which may need lifetime elision performed.
-                    let parent_def_id = |this: &mut Self, def_id: DefId| DefId {
-                        krate: def_id.krate,
-                        index: this.def_key(def_id).parent.expect("missing parent"),
-                    };
-                    let type_def_id = match partial_res.base_res() {
-                        Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
-                            Some(parent_def_id(self, def_id))
-                        }
-                        Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
-                            Some(parent_def_id(self, def_id))
-                        }
-                        Res::Def(DefKind::Struct, def_id)
-                        | Res::Def(DefKind::Union, def_id)
-                        | Res::Def(DefKind::Enum, def_id)
-                        | Res::Def(DefKind::TyAlias, def_id)
-                        | Res::Def(DefKind::Trait, def_id)
-                            if i + 1 == proj_start =>
-                        {
-                            Some(def_id)
-                        }
-                        _ => None,
-                    };
-                    let parenthesized_generic_args = match partial_res.base_res() {
-                        // `a::b::Trait(Args)`
-                        Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
-                            ParenthesizedGenericArgs::Ok
-                        }
-                        // `a::b::Trait(Args)::TraitItem`
-                        Res::Def(DefKind::Method, _)
-                        | Res::Def(DefKind::AssocConst, _)
-                        | Res::Def(DefKind::AssocTy, _)
-                            if i + 2 == proj_start =>
-                        {
-                            ParenthesizedGenericArgs::Ok
-                        }
-                        // Avoid duplicated errors.
-                        Res::Err => ParenthesizedGenericArgs::Ok,
-                        // An error
-                        _ => ParenthesizedGenericArgs::Err,
-                    };
-
-                    let num_lifetimes = type_def_id.map_or(0, |def_id| {
-                        if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
-                            return n;
-                        }
-                        assert!(!def_id.is_local());
-                        let item_generics = self
-                            .resolver
-                            .cstore()
-                            .item_generics_cloned_untracked(def_id, self.sess);
-                        let n = item_generics.own_counts().lifetimes;
-                        self.type_def_lifetime_params.insert(def_id, n);
-                        n
-                    });
-                    self.lower_path_segment(
-                        p.span,
-                        segment,
-                        param_mode,
-                        num_lifetimes,
-                        parenthesized_generic_args,
-                        itctx.reborrow(),
-                        None,
-                    )
-                },
-            )),
-            span: p.span,
-        });
-
-        // Simple case, either no projections, or only fully-qualified.
-        // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
-        if partial_res.unresolved_segments() == 0 {
-            return hir::QPath::Resolved(qself, path);
-        }
-
-        // Create the innermost type that we're projecting from.
-        let mut ty = if path.segments.is_empty() {
-            // If the base path is empty that means there exists a
-            // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
-            qself.expect("missing QSelf for <T>::...")
-        } else {
-            // Otherwise, the base path is an implicit `Self` type path,
-            // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
-            // `<I as Iterator>::Item::default`.
-            let new_id = self.next_id();
-            self.arena.alloc(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
-        };
-
-        // Anything after the base path are associated "extensions",
-        // out of which all but the last one are associated types,
-        // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
-        // * base path is `std::vec::Vec<T>`
-        // * "extensions" are `IntoIter`, `Item` and `clone`
-        // * type nodes are:
-        //   1. `std::vec::Vec<T>` (created above)
-        //   2. `<std::vec::Vec<T>>::IntoIter`
-        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
-        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
-        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
-            let segment = self.arena.alloc(self.lower_path_segment(
-                p.span,
-                segment,
-                param_mode,
-                0,
-                ParenthesizedGenericArgs::Err,
-                itctx.reborrow(),
-                None,
-            ));
-            let qpath = hir::QPath::TypeRelative(ty, segment);
-
-            // It's finished, return the extension of the right node type.
-            if i == p.segments.len() - 1 {
-                return qpath;
-            }
-
-            // Wrap the associated extension in another type node.
-            let new_id = self.next_id();
-            ty = self.arena.alloc(self.ty_path(new_id, p.span, qpath));
-        }
-
-        // We should've returned in the for loop above.
-        span_bug!(
-            p.span,
-            "lower_qpath: no final extension segment in {}..{}",
-            proj_start,
-            p.segments.len()
-        )
-    }
-
-    fn lower_path_extra(
-        &mut self,
-        res: Res,
-        p: &Path,
-        param_mode: ParamMode,
-        explicit_owner: Option<NodeId>,
-    ) -> &'hir hir::Path<'hir> {
-        self.arena.alloc(hir::Path {
-            res,
-            segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
-                self.lower_path_segment(
-                    p.span,
-                    segment,
-                    param_mode,
-                    0,
-                    ParenthesizedGenericArgs::Err,
-                    ImplTraitContext::disallowed(),
-                    explicit_owner,
-                )
-            })),
-            span: p.span,
-        })
-    }
-
-    fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> &'hir hir::Path<'hir> {
-        let res = self.expect_full_res(id);
-        let res = self.lower_res(res);
-        self.lower_path_extra(res, p, param_mode, None)
-    }
-
-    fn lower_path_segment(
-        &mut self,
-        path_span: Span,
-        segment: &PathSegment,
-        param_mode: ParamMode,
-        expected_lifetimes: usize,
-        parenthesized_generic_args: ParenthesizedGenericArgs,
-        itctx: ImplTraitContext<'_, 'hir>,
-        explicit_owner: Option<NodeId>,
-    ) -> hir::PathSegment<'hir> {
-        let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
-            let msg = "parenthesized type parameters may only be used with a `Fn` trait";
-            match **generic_args {
-                GenericArgs::AngleBracketed(ref data) => {
-                    self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
-                }
-                GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
-                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
-                    ParenthesizedGenericArgs::Err => {
-                        let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
-                        err.span_label(data.span, "only `Fn` traits may use parentheses");
-                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
-                            // Do not suggest going from `Trait()` to `Trait<>`
-                            if data.inputs.len() > 0 {
-                                if let Some(split) = snippet.find('(') {
-                                    let trait_name = &snippet[0..split];
-                                    let args = &snippet[split + 1..snippet.len() - 1];
-                                    err.span_suggestion(
-                                        data.span,
-                                        "use angle brackets instead",
-                                        format!("{}<{}>", trait_name, args),
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                }
-                            }
-                        };
-                        err.emit();
-                        (
-                            self.lower_angle_bracketed_parameter_data(
-                                &data.as_angle_bracketed_args(),
-                                param_mode,
-                                itctx,
-                            )
-                            .0,
-                            false,
-                        )
-                    }
-                },
-            }
-        } else {
-            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
-        };
-
-        let has_lifetimes = generic_args.args.iter().any(|arg| match arg {
-            GenericArg::Lifetime(_) => true,
-            _ => false,
-        });
-        let first_generic_span = generic_args
-            .args
-            .iter()
-            .map(|a| a.span())
-            .chain(generic_args.bindings.iter().map(|b| b.span))
-            .next();
-        if !generic_args.parenthesized && !has_lifetimes {
-            generic_args.args = self
-                .elided_path_lifetimes(path_span, expected_lifetimes)
-                .map(|lt| GenericArg::Lifetime(lt))
-                .chain(generic_args.args.into_iter())
-                .collect();
-            if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
-                let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
-                let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
-                let no_bindings = generic_args.bindings.is_empty();
-                let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings {
-                    // If there are no (non-implicit) generic args or associated type
-                    // bindings, our suggestion includes the angle brackets.
-                    (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion))
-                } else {
-                    // Otherwise (sorry, this is kind of gross) we need to infer the
-                    // place to splice in the `'_, ` from the generics that do exist.
-                    let first_generic_span = first_generic_span
-                        .expect("already checked that non-lifetime args or bindings exist");
-                    (false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
-                };
-                match self.anonymous_lifetime_mode {
-                    // In create-parameter mode we error here because we don't want to support
-                    // deprecated impl elision in new features like impl elision and `async fn`,
-                    // both of which work using the `CreateParameter` mode:
-                    //
-                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
-                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
-                    AnonymousLifetimeMode::CreateParameter => {
-                        let mut err = struct_span_err!(
-                            self.sess,
-                            path_span,
-                            E0726,
-                            "implicit elided lifetime not allowed here"
-                        );
-                        crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
-                            &self.sess,
-                            &mut err,
-                            expected_lifetimes,
-                            path_span,
-                            incl_angl_brckt,
-                            insertion_sp,
-                            suggestion,
-                        );
-                        err.emit();
-                    }
-                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
-                        self.resolver.lint_buffer().buffer_lint_with_diagnostic(
-                            ELIDED_LIFETIMES_IN_PATHS,
-                            CRATE_NODE_ID,
-                            path_span,
-                            "hidden lifetime parameters in types are deprecated",
-                            builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                                expected_lifetimes,
-                                path_span,
-                                incl_angl_brckt,
-                                insertion_sp,
-                                suggestion,
-                            ),
-                        );
-                    }
-                }
-            }
-        }
-
-        let res = self.expect_full_res(segment.id);
-        let id = if let Some(owner) = explicit_owner {
-            self.lower_node_id_with_owner(segment.id, owner)
-        } else {
-            self.lower_node_id(segment.id)
-        };
-        debug!(
-            "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
-            segment.ident, segment.id, id,
-        );
-
-        hir::PathSegment {
-            ident: segment.ident,
-            hir_id: Some(id),
-            res: Some(self.lower_res(res)),
-            infer_args,
-            args: if generic_args.is_empty() {
-                None
-            } else {
-                Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
-            },
-        }
-    }
-
-    fn lower_angle_bracketed_parameter_data(
-        &mut self,
-        data: &AngleBracketedArgs,
-        param_mode: ParamMode,
-        mut itctx: ImplTraitContext<'_, 'hir>,
-    ) -> (GenericArgsCtor<'hir>, bool) {
-        let &AngleBracketedArgs { ref args, ref constraints, .. } = data;
-        let has_non_lt_args = args.iter().any(|arg| match arg {
-            ast::GenericArg::Lifetime(_) => false,
-            ast::GenericArg::Type(_) => true,
-            ast::GenericArg::Const(_) => true,
-        });
-        (
-            GenericArgsCtor {
-                args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
-                bindings: self.arena.alloc_from_iter(
-                    constraints.iter().map(|b| self.lower_assoc_ty_constraint(b, itctx.reborrow())),
-                ),
-                parenthesized: false,
-            },
-            !has_non_lt_args && param_mode == ParamMode::Optional,
-        )
-    }
-
-    fn lower_parenthesized_parameter_data(
-        &mut self,
-        data: &ParenthesizedArgs,
-    ) -> (GenericArgsCtor<'hir>, bool) {
-        // Switch to `PassThrough` mode for anonymous lifetimes; this
-        // means that we permit things like `&Ref<T>`, where `Ref` has
-        // a hidden lifetime parameter. This is needed for backwards
-        // compatibility, even in contexts like an impl header where
-        // we generally don't permit such things (see #51008).
-        self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
-            let &ParenthesizedArgs { ref inputs, ref output, span } = data;
-            let inputs = this.arena.alloc_from_iter(
-                inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
-            );
-            let output_ty = match output {
-                FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
-                FunctionRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
-            };
-            let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
-            let binding = hir::TypeBinding {
-                hir_id: this.next_id(),
-                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
-                span: output_ty.span,
-                kind: hir::TypeBindingKind::Equality { ty: output_ty },
-            };
-            (
-                GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
-                false,
-            )
-        })
-    }
-
     fn lower_local(&mut self, l: &Local) -> (hir::Local<'hir>, SmallVec<[NodeId; 1]>) {
         let mut ids = SmallVec::<[NodeId; 1]>::new();
         if self.sess.features_untracked().impl_trait_in_bindings {
@@ -2385,12 +1974,7 @@
         // "<Output = T>"
         let future_params = self.arena.alloc(hir::GenericArgs {
             args: &[],
-            bindings: arena_vec![self; hir::TypeBinding {
-                ident: Ident::with_dummy_span(FN_OUTPUT_NAME),
-                kind: hir::TypeBindingKind::Equality { ty: output_ty },
-                hir_id: self.next_id(),
-                span,
-            }],
+            bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
             parenthesized: false,
         });
 
@@ -2541,12 +2125,14 @@
 
                 (hir::ParamName::Plain(param.ident), kind)
             }
-            GenericParamKind::Const { ref ty } => (
-                hir::ParamName::Plain(param.ident),
-                hir::GenericParamKind::Const {
-                    ty: self.lower_ty(&ty, ImplTraitContext::disallowed()),
-                },
-            ),
+            GenericParamKind::Const { ref ty } => {
+                let ty = self
+                    .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
+                        this.lower_ty(&ty, ImplTraitContext::disallowed())
+                    });
+
+                (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty })
+            }
         };
 
         hir::GenericParam {
@@ -2646,250 +2232,6 @@
         self.expr_block(block, AttrVec::new())
     }
 
-    fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
-        let node = match p.kind {
-            PatKind::Wild => hir::PatKind::Wild,
-            PatKind::Ident(ref binding_mode, ident, ref sub) => {
-                let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
-                let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
-                node
-            }
-            PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
-            PatKind::TupleStruct(ref path, ref pats) => {
-                let qpath = self.lower_qpath(
-                    p.id,
-                    &None,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                );
-                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
-                hir::PatKind::TupleStruct(qpath, pats, ddpos)
-            }
-            PatKind::Or(ref pats) => {
-                hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
-            }
-            PatKind::Path(ref qself, ref path) => {
-                let qpath = self.lower_qpath(
-                    p.id,
-                    qself,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                );
-                hir::PatKind::Path(qpath)
-            }
-            PatKind::Struct(ref path, ref fields, etc) => {
-                let qpath = self.lower_qpath(
-                    p.id,
-                    &None,
-                    path,
-                    ParamMode::Optional,
-                    ImplTraitContext::disallowed(),
-                );
-
-                let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
-                    hir_id: self.next_id(),
-                    ident: f.ident,
-                    pat: self.lower_pat(&f.pat),
-                    is_shorthand: f.is_shorthand,
-                    span: f.span,
-                }));
-                hir::PatKind::Struct(qpath, fs, etc)
-            }
-            PatKind::Tuple(ref pats) => {
-                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
-                hir::PatKind::Tuple(pats, ddpos)
-            }
-            PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
-            PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
-            PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
-                self.lower_expr(e1),
-                self.lower_expr(e2),
-                self.lower_range_end(end),
-            ),
-            PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
-            PatKind::Rest => {
-                // If we reach here the `..` pattern is not semantically allowed.
-                self.ban_illegal_rest_pat(p.span)
-            }
-            PatKind::Paren(ref inner) => return self.lower_pat(inner),
-            PatKind::Mac(_) => panic!("Shouldn't exist here"),
-        };
-
-        self.pat_with_node_id_of(p, node)
-    }
-
-    fn lower_pat_tuple(
-        &mut self,
-        pats: &[AstP<Pat>],
-        ctx: &str,
-    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
-        let mut elems = Vec::with_capacity(pats.len());
-        let mut rest = None;
-
-        let mut iter = pats.iter().enumerate();
-        for (idx, pat) in iter.by_ref() {
-            // Interpret the first `..` pattern as a sub-tuple pattern.
-            // Note that unlike for slice patterns,
-            // where `xs @ ..` is a legal sub-slice pattern,
-            // it is not a legal sub-tuple pattern.
-            if pat.is_rest() {
-                rest = Some((idx, pat.span));
-                break;
-            }
-            // It was not a sub-tuple pattern so lower it normally.
-            elems.push(self.lower_pat(pat));
-        }
-
-        for (_, pat) in iter {
-            // There was a previous sub-tuple pattern; make sure we don't allow more...
-            if pat.is_rest() {
-                // ...but there was one again, so error.
-                self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
-            } else {
-                elems.push(self.lower_pat(pat));
-            }
-        }
-
-        (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
-    }
-
-    /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
-    /// `hir::PatKind::Slice(before, slice, after)`.
-    ///
-    /// When encountering `($binding_mode $ident @)? ..` (`slice`),
-    /// this is interpreted as a sub-slice pattern semantically.
-    /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
-    fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind<'hir> {
-        let mut before = Vec::new();
-        let mut after = Vec::new();
-        let mut slice = None;
-        let mut prev_rest_span = None;
-
-        let mut iter = pats.iter();
-        // Lower all the patterns until the first occurence of a sub-slice pattern.
-        for pat in iter.by_ref() {
-            match pat.kind {
-                // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
-                PatKind::Rest => {
-                    prev_rest_span = Some(pat.span);
-                    slice = Some(self.pat_wild_with_node_id_of(pat));
-                    break;
-                }
-                // Found a sub-slice pattern `$binding_mode $ident @ ..`.
-                // Record, lower it to `$binding_mode $ident @ _`, and stop here.
-                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
-                    prev_rest_span = Some(sub.span);
-                    let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
-                    let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
-                    slice = Some(self.pat_with_node_id_of(pat, node));
-                    break;
-                }
-                // It was not a subslice pattern so lower it normally.
-                _ => before.push(self.lower_pat(pat)),
-            }
-        }
-
-        // Lower all the patterns after the first sub-slice pattern.
-        for pat in iter {
-            // There was a previous subslice pattern; make sure we don't allow more.
-            let rest_span = match pat.kind {
-                PatKind::Rest => Some(pat.span),
-                PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
-                    // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
-                    after.push(self.pat_wild_with_node_id_of(pat));
-                    Some(sub.span)
-                }
-                _ => None,
-            };
-            if let Some(rest_span) = rest_span {
-                // We have e.g., `[a, .., b, ..]`. That's no good, error!
-                self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
-            } else {
-                // Lower the pattern normally.
-                after.push(self.lower_pat(pat));
-            }
-        }
-
-        hir::PatKind::Slice(
-            self.arena.alloc_from_iter(before),
-            slice,
-            self.arena.alloc_from_iter(after),
-        )
-    }
-
-    fn lower_pat_ident(
-        &mut self,
-        p: &Pat,
-        binding_mode: &BindingMode,
-        ident: Ident,
-        lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
-    ) -> hir::PatKind<'hir> {
-        match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
-            // `None` can occur in body-less function signatures
-            res @ None | res @ Some(Res::Local(_)) => {
-                let canonical_id = match res {
-                    Some(Res::Local(id)) => id,
-                    _ => p.id,
-                };
-
-                hir::PatKind::Binding(
-                    self.lower_binding_mode(binding_mode),
-                    self.lower_node_id(canonical_id),
-                    ident,
-                    lower_sub(self),
-                )
-            }
-            Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
-                None,
-                self.arena.alloc(hir::Path {
-                    span: ident.span,
-                    res: self.lower_res(res),
-                    segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
-                }),
-            )),
-        }
-    }
-
-    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
-        self.pat_with_node_id_of(p, hir::PatKind::Wild)
-    }
-
-    /// Construct a `Pat` with the `HirId` of `p.id` lowered.
-    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
-        self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
-    }
-
-    /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
-    fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
-        self.diagnostic()
-            .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
-            .span_label(sp, &format!("can only be used once per {} pattern", ctx))
-            .span_label(prev_sp, "previously used here")
-            .emit();
-    }
-
-    /// Used to ban the `..` pattern in places it shouldn't be semantically.
-    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
-        self.diagnostic()
-            .struct_span_err(sp, "`..` patterns are not allowed here")
-            .note("only allowed in tuple, tuple struct, and slice patterns")
-            .emit();
-
-        // We're not in a list context so `..` can be reasonably treated
-        // as `_` because it should always be valid and roughly matches the
-        // intent of `..` (notice that the rest of a single slot is that slot).
-        hir::PatKind::Wild
-    }
-
-    fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
-        match *e {
-            RangeEnd::Included(_) => hir::RangeEnd::Included,
-            RangeEnd::Excluded => hir::RangeEnd::Excluded,
-        }
-    }
-
     fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
         self.with_new_scopes(|this| hir::AnonConst {
             hir_id: this.lower_node_id(c.id),
@@ -2949,15 +2291,6 @@
         }
     }
 
-    fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
-        match *b {
-            BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
-            BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
-            BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
-            BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
-        }
-    }
-
     fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
         match u {
             CompilerGenerated => hir::UnsafeSource::CompilerGenerated,
@@ -2968,7 +2301,13 @@
     fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
         match f {
             TraitBoundModifier::None => hir::TraitBoundModifier::None,
-            TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
+            TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst,
+
+            // `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a
+            // placeholder for compilation to proceed.
+            TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
+                hir::TraitBoundModifier::Maybe
+            }
         }
     }
 
@@ -3286,7 +2625,7 @@
                 id,
                 span,
                 "trait objects without an explicit `dyn` are deprecated",
-                builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
+                BuiltinLintDiagnostics::BareTraitObject(span, is_global),
             )
         }
     }
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
new file mode 100644
index 0000000..6cf640a
--- /dev/null
+++ b/src/librustc_ast_lowering/pat.rs
@@ -0,0 +1,263 @@
+use super::{ImplTraitContext, LoweringContext, ParamMode};
+
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_span::{source_map::Spanned, Span};
+use syntax::ast::*;
+use syntax::ptr::P;
+
+impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    crate fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
+        let node = match p.kind {
+            PatKind::Wild => hir::PatKind::Wild,
+            PatKind::Ident(ref binding_mode, ident, ref sub) => {
+                let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
+                let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
+                node
+            }
+            PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
+            PatKind::TupleStruct(ref path, ref pats) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    &None,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::disallowed(),
+                );
+                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
+                hir::PatKind::TupleStruct(qpath, pats, ddpos)
+            }
+            PatKind::Or(ref pats) => {
+                hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
+            }
+            PatKind::Path(ref qself, ref path) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    qself,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::disallowed(),
+                );
+                hir::PatKind::Path(qpath)
+            }
+            PatKind::Struct(ref path, ref fields, etc) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    &None,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::disallowed(),
+                );
+
+                let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
+                    hir_id: self.next_id(),
+                    ident: f.ident,
+                    pat: self.lower_pat(&f.pat),
+                    is_shorthand: f.is_shorthand,
+                    span: f.span,
+                }));
+                hir::PatKind::Struct(qpath, fs, etc)
+            }
+            PatKind::Tuple(ref pats) => {
+                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
+                hir::PatKind::Tuple(pats, ddpos)
+            }
+            PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
+            PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
+            PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
+                e1.as_deref().map(|e| self.lower_expr(e)),
+                e2.as_deref().map(|e| self.lower_expr(e)),
+                self.lower_range_end(end, e2.is_some()),
+            ),
+            PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
+            PatKind::Rest => {
+                // If we reach here the `..` pattern is not semantically allowed.
+                self.ban_illegal_rest_pat(p.span)
+            }
+            PatKind::Paren(ref inner) => return self.lower_pat(inner),
+            PatKind::Mac(_) => panic!("Shouldn't exist here"),
+        };
+
+        self.pat_with_node_id_of(p, node)
+    }
+
+    fn lower_pat_tuple(
+        &mut self,
+        pats: &[P<Pat>],
+        ctx: &str,
+    ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
+        let mut elems = Vec::with_capacity(pats.len());
+        let mut rest = None;
+
+        let mut iter = pats.iter().enumerate();
+        for (idx, pat) in iter.by_ref() {
+            // Interpret the first `..` pattern as a sub-tuple pattern.
+            // Note that unlike for slice patterns,
+            // where `xs @ ..` is a legal sub-slice pattern,
+            // it is not a legal sub-tuple pattern.
+            if pat.is_rest() {
+                rest = Some((idx, pat.span));
+                break;
+            }
+            // It was not a sub-tuple pattern so lower it normally.
+            elems.push(self.lower_pat(pat));
+        }
+
+        for (_, pat) in iter {
+            // There was a previous sub-tuple pattern; make sure we don't allow more...
+            if pat.is_rest() {
+                // ...but there was one again, so error.
+                self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
+            } else {
+                elems.push(self.lower_pat(pat));
+            }
+        }
+
+        (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
+    }
+
+    /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
+    /// `hir::PatKind::Slice(before, slice, after)`.
+    ///
+    /// When encountering `($binding_mode $ident @)? ..` (`slice`),
+    /// this is interpreted as a sub-slice pattern semantically.
+    /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
+    fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
+        let mut before = Vec::new();
+        let mut after = Vec::new();
+        let mut slice = None;
+        let mut prev_rest_span = None;
+
+        let mut iter = pats.iter();
+        // Lower all the patterns until the first occurence of a sub-slice pattern.
+        for pat in iter.by_ref() {
+            match pat.kind {
+                // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
+                PatKind::Rest => {
+                    prev_rest_span = Some(pat.span);
+                    slice = Some(self.pat_wild_with_node_id_of(pat));
+                    break;
+                }
+                // Found a sub-slice pattern `$binding_mode $ident @ ..`.
+                // Record, lower it to `$binding_mode $ident @ _`, and stop here.
+                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
+                    prev_rest_span = Some(sub.span);
+                    let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
+                    let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
+                    slice = Some(self.pat_with_node_id_of(pat, node));
+                    break;
+                }
+                // It was not a subslice pattern so lower it normally.
+                _ => before.push(self.lower_pat(pat)),
+            }
+        }
+
+        // Lower all the patterns after the first sub-slice pattern.
+        for pat in iter {
+            // There was a previous subslice pattern; make sure we don't allow more.
+            let rest_span = match pat.kind {
+                PatKind::Rest => Some(pat.span),
+                PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
+                    // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
+                    after.push(self.pat_wild_with_node_id_of(pat));
+                    Some(sub.span)
+                }
+                _ => None,
+            };
+            if let Some(rest_span) = rest_span {
+                // We have e.g., `[a, .., b, ..]`. That's no good, error!
+                self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
+            } else {
+                // Lower the pattern normally.
+                after.push(self.lower_pat(pat));
+            }
+        }
+
+        hir::PatKind::Slice(
+            self.arena.alloc_from_iter(before),
+            slice,
+            self.arena.alloc_from_iter(after),
+        )
+    }
+
+    fn lower_pat_ident(
+        &mut self,
+        p: &Pat,
+        binding_mode: &BindingMode,
+        ident: Ident,
+        lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
+    ) -> hir::PatKind<'hir> {
+        match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
+            // `None` can occur in body-less function signatures
+            res @ None | res @ Some(Res::Local(_)) => {
+                let canonical_id = match res {
+                    Some(Res::Local(id)) => id,
+                    _ => p.id,
+                };
+
+                hir::PatKind::Binding(
+                    self.lower_binding_mode(binding_mode),
+                    self.lower_node_id(canonical_id),
+                    ident,
+                    lower_sub(self),
+                )
+            }
+            Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
+                None,
+                self.arena.alloc(hir::Path {
+                    span: ident.span,
+                    res: self.lower_res(res),
+                    segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
+                }),
+            )),
+        }
+    }
+
+    fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
+        match *b {
+            BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
+            BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
+            BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
+            BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
+        }
+    }
+
+    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
+        self.pat_with_node_id_of(p, hir::PatKind::Wild)
+    }
+
+    /// Construct a `Pat` with the `HirId` of `p.id` lowered.
+    fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
+        self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
+    }
+
+    /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
+    fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
+        self.diagnostic()
+            .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
+            .span_label(sp, &format!("can only be used once per {} pattern", ctx))
+            .span_label(prev_sp, "previously used here")
+            .emit();
+    }
+
+    /// Used to ban the `..` pattern in places it shouldn't be semantically.
+    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
+        self.diagnostic()
+            .struct_span_err(sp, "`..` patterns are not allowed here")
+            .note("only allowed in tuple, tuple struct, and slice patterns")
+            .emit();
+
+        // We're not in a list context so `..` can be reasonably treated
+        // as `_` because it should always be valid and roughly matches the
+        // intent of `..` (notice that the rest of a single slot is that slot).
+        hir::PatKind::Wild
+    }
+
+    fn lower_range_end(&mut self, e: &RangeEnd, has_end: bool) -> hir::RangeEnd {
+        match *e {
+            RangeEnd::Excluded if has_end => hir::RangeEnd::Excluded,
+            // No end; so `X..` behaves like `RangeFrom`.
+            RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included,
+        }
+    }
+}
diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs
new file mode 100644
index 0000000..e5f7df6
--- /dev/null
+++ b/src/librustc_ast_lowering/path.rs
@@ -0,0 +1,422 @@
+use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
+use super::{GenericArgsCtor, ParenthesizedGenericArgs};
+
+use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
+use rustc::span_bug;
+use rustc_errors::{struct_span_err, Applicability};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, PartialRes, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::GenericArg;
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_span::Span;
+use syntax::ast::{self, *};
+
+use log::debug;
+use smallvec::smallvec;
+
+impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    crate fn lower_qpath(
+        &mut self,
+        id: NodeId,
+        qself: &Option<QSelf>,
+        p: &Path,
+        param_mode: ParamMode,
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> hir::QPath<'hir> {
+        let qself_position = qself.as_ref().map(|q| q.position);
+        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
+
+        let partial_res =
+            self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
+
+        let proj_start = p.segments.len() - partial_res.unresolved_segments();
+        let path = self.arena.alloc(hir::Path {
+            res: self.lower_res(partial_res.base_res()),
+            segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
+                |(i, segment)| {
+                    let param_mode = match (qself_position, param_mode) {
+                        (Some(j), ParamMode::Optional) if i < j => {
+                            // This segment is part of the trait path in a
+                            // qualified path - one of `a`, `b` or `Trait`
+                            // in `<X as a::b::Trait>::T::U::method`.
+                            ParamMode::Explicit
+                        }
+                        _ => param_mode,
+                    };
+
+                    // Figure out if this is a type/trait segment,
+                    // which may need lifetime elision performed.
+                    let parent_def_id = |this: &mut Self, def_id: DefId| DefId {
+                        krate: def_id.krate,
+                        index: this.resolver.def_key(def_id).parent.expect("missing parent"),
+                    };
+                    let type_def_id = match partial_res.base_res() {
+                        Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
+                            Some(parent_def_id(self, def_id))
+                        }
+                        Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
+                            Some(parent_def_id(self, def_id))
+                        }
+                        Res::Def(DefKind::Struct, def_id)
+                        | Res::Def(DefKind::Union, def_id)
+                        | Res::Def(DefKind::Enum, def_id)
+                        | Res::Def(DefKind::TyAlias, def_id)
+                        | Res::Def(DefKind::Trait, def_id)
+                            if i + 1 == proj_start =>
+                        {
+                            Some(def_id)
+                        }
+                        _ => None,
+                    };
+                    let parenthesized_generic_args = match partial_res.base_res() {
+                        // `a::b::Trait(Args)`
+                        Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
+                            ParenthesizedGenericArgs::Ok
+                        }
+                        // `a::b::Trait(Args)::TraitItem`
+                        Res::Def(DefKind::Method, _)
+                        | Res::Def(DefKind::AssocConst, _)
+                        | Res::Def(DefKind::AssocTy, _)
+                            if i + 2 == proj_start =>
+                        {
+                            ParenthesizedGenericArgs::Ok
+                        }
+                        // Avoid duplicated errors.
+                        Res::Err => ParenthesizedGenericArgs::Ok,
+                        // An error
+                        _ => ParenthesizedGenericArgs::Err,
+                    };
+
+                    let num_lifetimes = type_def_id.map_or(0, |def_id| {
+                        if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
+                            return n;
+                        }
+                        assert!(!def_id.is_local());
+                        let n = self.resolver.item_generics_num_lifetimes(def_id, self.sess);
+                        self.type_def_lifetime_params.insert(def_id, n);
+                        n
+                    });
+                    self.lower_path_segment(
+                        p.span,
+                        segment,
+                        param_mode,
+                        num_lifetimes,
+                        parenthesized_generic_args,
+                        itctx.reborrow(),
+                        None,
+                    )
+                },
+            )),
+            span: p.span,
+        });
+
+        // Simple case, either no projections, or only fully-qualified.
+        // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
+        if partial_res.unresolved_segments() == 0 {
+            return hir::QPath::Resolved(qself, path);
+        }
+
+        // Create the innermost type that we're projecting from.
+        let mut ty = if path.segments.is_empty() {
+            // If the base path is empty that means there exists a
+            // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
+            qself.expect("missing QSelf for <T>::...")
+        } else {
+            // Otherwise, the base path is an implicit `Self` type path,
+            // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
+            // `<I as Iterator>::Item::default`.
+            let new_id = self.next_id();
+            self.arena.alloc(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
+        };
+
+        // Anything after the base path are associated "extensions",
+        // out of which all but the last one are associated types,
+        // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
+        // * base path is `std::vec::Vec<T>`
+        // * "extensions" are `IntoIter`, `Item` and `clone`
+        // * type nodes are:
+        //   1. `std::vec::Vec<T>` (created above)
+        //   2. `<std::vec::Vec<T>>::IntoIter`
+        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
+        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
+        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
+            let segment = self.arena.alloc(self.lower_path_segment(
+                p.span,
+                segment,
+                param_mode,
+                0,
+                ParenthesizedGenericArgs::Err,
+                itctx.reborrow(),
+                None,
+            ));
+            let qpath = hir::QPath::TypeRelative(ty, segment);
+
+            // It's finished, return the extension of the right node type.
+            if i == p.segments.len() - 1 {
+                return qpath;
+            }
+
+            // Wrap the associated extension in another type node.
+            let new_id = self.next_id();
+            ty = self.arena.alloc(self.ty_path(new_id, p.span, qpath));
+        }
+
+        // We should've returned in the for loop above.
+        span_bug!(
+            p.span,
+            "lower_qpath: no final extension segment in {}..{}",
+            proj_start,
+            p.segments.len()
+        )
+    }
+
+    crate fn lower_path_extra(
+        &mut self,
+        res: Res,
+        p: &Path,
+        param_mode: ParamMode,
+        explicit_owner: Option<NodeId>,
+    ) -> &'hir hir::Path<'hir> {
+        self.arena.alloc(hir::Path {
+            res,
+            segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
+                self.lower_path_segment(
+                    p.span,
+                    segment,
+                    param_mode,
+                    0,
+                    ParenthesizedGenericArgs::Err,
+                    ImplTraitContext::disallowed(),
+                    explicit_owner,
+                )
+            })),
+            span: p.span,
+        })
+    }
+
+    crate fn lower_path(
+        &mut self,
+        id: NodeId,
+        p: &Path,
+        param_mode: ParamMode,
+    ) -> &'hir hir::Path<'hir> {
+        let res = self.expect_full_res(id);
+        let res = self.lower_res(res);
+        self.lower_path_extra(res, p, param_mode, None)
+    }
+
+    crate fn lower_path_segment(
+        &mut self,
+        path_span: Span,
+        segment: &PathSegment,
+        param_mode: ParamMode,
+        expected_lifetimes: usize,
+        parenthesized_generic_args: ParenthesizedGenericArgs,
+        itctx: ImplTraitContext<'_, 'hir>,
+        explicit_owner: Option<NodeId>,
+    ) -> hir::PathSegment<'hir> {
+        let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
+            let msg = "parenthesized type parameters may only be used with a `Fn` trait";
+            match **generic_args {
+                GenericArgs::AngleBracketed(ref data) => {
+                    self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
+                }
+                GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
+                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+                    ParenthesizedGenericArgs::Err => {
+                        let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
+                        err.span_label(data.span, "only `Fn` traits may use parentheses");
+                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
+                            // Do not suggest going from `Trait()` to `Trait<>`
+                            if data.inputs.len() > 0 {
+                                if let Some(split) = snippet.find('(') {
+                                    let trait_name = &snippet[0..split];
+                                    let args = &snippet[split + 1..snippet.len() - 1];
+                                    err.span_suggestion(
+                                        data.span,
+                                        "use angle brackets instead",
+                                        format!("{}<{}>", trait_name, args),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                            }
+                        };
+                        err.emit();
+                        (
+                            self.lower_angle_bracketed_parameter_data(
+                                &data.as_angle_bracketed_args(),
+                                param_mode,
+                                itctx,
+                            )
+                            .0,
+                            false,
+                        )
+                    }
+                },
+            }
+        } else {
+            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
+        };
+
+        let has_lifetimes = generic_args.args.iter().any(|arg| match arg {
+            GenericArg::Lifetime(_) => true,
+            _ => false,
+        });
+        let first_generic_span = generic_args
+            .args
+            .iter()
+            .map(|a| a.span())
+            .chain(generic_args.bindings.iter().map(|b| b.span))
+            .next();
+        if !generic_args.parenthesized && !has_lifetimes {
+            generic_args.args = self
+                .elided_path_lifetimes(path_span, expected_lifetimes)
+                .map(|lt| GenericArg::Lifetime(lt))
+                .chain(generic_args.args.into_iter())
+                .collect();
+            if expected_lifetimes > 0 && param_mode == ParamMode::Explicit {
+                let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
+                let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
+                let no_bindings = generic_args.bindings.is_empty();
+                let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings {
+                    // If there are no (non-implicit) generic args or associated type
+                    // bindings, our suggestion includes the angle brackets.
+                    (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion))
+                } else {
+                    // Otherwise (sorry, this is kind of gross) we need to infer the
+                    // place to splice in the `'_, ` from the generics that do exist.
+                    let first_generic_span = first_generic_span
+                        .expect("already checked that non-lifetime args or bindings exist");
+                    (false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
+                };
+                match self.anonymous_lifetime_mode {
+                    // In create-parameter mode we error here because we don't want to support
+                    // deprecated impl elision in new features like impl elision and `async fn`,
+                    // both of which work using the `CreateParameter` mode:
+                    //
+                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
+                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
+                    AnonymousLifetimeMode::CreateParameter => {
+                        let mut err = struct_span_err!(
+                            self.sess,
+                            path_span,
+                            E0726,
+                            "implicit elided lifetime not allowed here"
+                        );
+                        rustc::lint::add_elided_lifetime_in_path_suggestion(
+                            &self.sess,
+                            &mut err,
+                            expected_lifetimes,
+                            path_span,
+                            incl_angl_brckt,
+                            insertion_sp,
+                            suggestion,
+                        );
+                        err.emit();
+                    }
+                    AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
+                        self.resolver.lint_buffer().buffer_lint_with_diagnostic(
+                            ELIDED_LIFETIMES_IN_PATHS,
+                            CRATE_NODE_ID,
+                            path_span,
+                            "hidden lifetime parameters in types are deprecated",
+                            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                                expected_lifetimes,
+                                path_span,
+                                incl_angl_brckt,
+                                insertion_sp,
+                                suggestion,
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+
+        let res = self.expect_full_res(segment.id);
+        let id = if let Some(owner) = explicit_owner {
+            self.lower_node_id_with_owner(segment.id, owner)
+        } else {
+            self.lower_node_id(segment.id)
+        };
+        debug!(
+            "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
+            segment.ident, segment.id, id,
+        );
+
+        hir::PathSegment {
+            ident: segment.ident,
+            hir_id: Some(id),
+            res: Some(self.lower_res(res)),
+            infer_args,
+            args: if generic_args.is_empty() {
+                None
+            } else {
+                Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
+            },
+        }
+    }
+
+    fn lower_angle_bracketed_parameter_data(
+        &mut self,
+        data: &AngleBracketedArgs,
+        param_mode: ParamMode,
+        mut itctx: ImplTraitContext<'_, 'hir>,
+    ) -> (GenericArgsCtor<'hir>, bool) {
+        let &AngleBracketedArgs { ref args, ref constraints, .. } = data;
+        let has_non_lt_args = args.iter().any(|arg| match arg {
+            ast::GenericArg::Lifetime(_) => false,
+            ast::GenericArg::Type(_) => true,
+            ast::GenericArg::Const(_) => true,
+        });
+        (
+            GenericArgsCtor {
+                args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
+                bindings: self.arena.alloc_from_iter(
+                    constraints.iter().map(|b| self.lower_assoc_ty_constraint(b, itctx.reborrow())),
+                ),
+                parenthesized: false,
+            },
+            !has_non_lt_args && param_mode == ParamMode::Optional,
+        )
+    }
+
+    fn lower_parenthesized_parameter_data(
+        &mut self,
+        data: &ParenthesizedArgs,
+    ) -> (GenericArgsCtor<'hir>, bool) {
+        // Switch to `PassThrough` mode for anonymous lifetimes; this
+        // means that we permit things like `&Ref<T>`, where `Ref` has
+        // a hidden lifetime parameter. This is needed for backwards
+        // compatibility, even in contexts like an impl header where
+        // we generally don't permit such things (see #51008).
+        self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
+            let &ParenthesizedArgs { ref inputs, ref output, span } = data;
+            let inputs = this.arena.alloc_from_iter(
+                inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
+            );
+            let output_ty = match output {
+                FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
+                FunctionRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
+            };
+            let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
+            let binding = this.output_ty_binding(output_ty.span, output_ty);
+            (
+                GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
+                false,
+            )
+        })
+    }
+
+    /// An associated type binding `Output = $ty`.
+    crate fn output_ty_binding(
+        &mut self,
+        span: Span,
+        ty: &'hir hir::Ty<'hir>,
+    ) -> hir::TypeBinding<'hir> {
+        let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
+        let kind = hir::TypeBindingKind::Equality { ty };
+        hir::TypeBinding { hir_id: self.next_id(), span, ident, kind }
+    }
+}
diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml
new file mode 100644
index 0000000..25b1ace
--- /dev/null
+++ b/src/librustc_ast_passes/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_ast_passes"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_ast_passes"
+path = "lib.rs"
+
+[dependencies]
+log = "0.4"
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_feature = { path = "../librustc_feature" }
+rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
+syntax = { path = "../libsyntax" }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
similarity index 87%
rename from src/librustc_passes/ast_validation.rs
rename to src/librustc_ast_passes/ast_validation.rs
index 038c428..152086b 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -6,11 +6,12 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
-use errors::{Applicability, FatalError};
-use rustc::lint;
-use rustc::session::Session;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, Applicability, FatalError};
 use rustc_parse::validate_attr;
+use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
+use rustc_session::lint::LintBuffer;
+use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -20,9 +21,25 @@
 use syntax::expand::is_proc_macro_attr;
 use syntax::print::pprust;
 use syntax::visit::{self, Visitor};
-use syntax::{span_err, struct_span_err, walk_list};
+use syntax::walk_list;
 
-use rustc_error_codes::*;
+/// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
+#[derive(Clone, Copy)]
+enum BoundContext {
+    ImplTrait,
+    TraitBounds,
+    TraitObject,
+}
+
+impl BoundContext {
+    fn description(&self) -> &'static str {
+        match self {
+            Self::ImplTrait => "`impl Trait`",
+            Self::TraitBounds => "supertraits",
+            Self::TraitObject => "trait objects",
+        }
+    }
+}
 
 struct AstValidator<'a> {
     session: &'a Session,
@@ -33,6 +50,12 @@
     /// e.g., `impl Iterator<Item = impl Debug>`.
     outer_impl_trait: Option<Span>,
 
+    /// Keeps track of the `BoundContext` as we recurse.
+    ///
+    /// This is used to forbid `?const Trait` bounds in, e.g.,
+    /// `impl Iterator<Item = Box<dyn ?const Trait>`.
+    bound_context: Option<BoundContext>,
+
     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
     /// or `Foo::Bar<impl Trait>`
     is_impl_trait_banned: bool,
@@ -41,7 +64,7 @@
     /// certain positions.
     is_assoc_ty_bound_banned: bool,
 
-    lint_buffer: &'a mut lint::LintBuffer,
+    lint_buffer: &'a mut LintBuffer,
 }
 
 impl<'a> AstValidator<'a> {
@@ -59,10 +82,20 @@
 
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.outer_impl_trait, outer);
-        f(self);
+        if outer.is_some() {
+            self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
+        } else {
+            f(self)
+        }
         self.outer_impl_trait = old;
     }
 
+    fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
+        let old = self.bound_context.replace(ctx);
+        f(self);
+        self.bound_context = old;
+    }
+
     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
         match constraint.kind {
             AssocTyConstraintKind::Equality { .. } => {}
@@ -84,6 +117,9 @@
             TyKind::ImplTrait(..) => {
                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
             }
+            TyKind::TraitObject(..) => {
+                self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
+            }
             TyKind::Path(ref qself, ref path) => {
                 // We allow these:
                 //  - `Option<impl Trait>`
@@ -121,7 +157,7 @@
         }
     }
 
-    fn err_handler(&self) -> &errors::Handler {
+    fn err_handler(&self) -> &rustc_errors::Handler {
         &self.session.diagnostic()
     }
 
@@ -192,6 +228,7 @@
         }
     }
 
+    // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
     fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
         for bound in bounds {
             if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
@@ -371,7 +408,7 @@
 
 fn validate_generics_order<'a>(
     sess: &Session,
-    handler: &errors::Handler,
+    handler: &rustc_errors::Handler,
     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
     pos: GenericPosition,
     span: Span,
@@ -470,7 +507,13 @@
                 self.check_fn_decl(fn_decl);
             }
             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
-                span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
+                struct_span_err!(
+                    self.session,
+                    expr.span,
+                    E0472,
+                    "asm! is unsupported on this target"
+                )
+                .emit();
             }
             _ => {}
         }
@@ -498,12 +541,13 @@
                 for bound in bounds {
                     if let GenericBound::Outlives(ref lifetime) = *bound {
                         if any_lifetime_bounds {
-                            span_err!(
+                            struct_span_err!(
                                 self.session,
                                 lifetime.ident.span,
                                 E0226,
                                 "only a single explicit lifetime bound is permitted"
-                            );
+                            )
+                            .emit();
                             break;
                         }
                         any_lifetime_bounds = true;
@@ -566,18 +610,33 @@
         }
 
         match item.kind {
-            ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
+            ItemKind::Impl {
+                unsafety,
+                polarity,
+                defaultness: _,
+                constness: _,
+                generics: _,
+                of_trait: Some(_),
+                ref self_ty,
+                ref items,
+            } => {
                 self.invalid_visibility(&item.vis, None);
-                if let TyKind::Err = ty.kind {
+                if let TyKind::Err = self_ty.kind {
                     self.err_handler()
                         .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
                         .help("use `auto trait Trait {}` instead")
                         .emit();
                 }
                 if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
-                    span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
+                    struct_span_err!(
+                        self.session,
+                        item.span,
+                        E0198,
+                        "negative impls cannot be unsafe"
+                    )
+                    .emit();
                 }
-                for impl_item in impl_items {
+                for impl_item in items {
                     self.invalid_visibility(&impl_item.vis, None);
                     if let AssocItemKind::Fn(ref sig, _) = impl_item.kind {
                         self.check_trait_fn_not_const(sig.header.constness);
@@ -585,13 +644,28 @@
                     }
                 }
             }
-            ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
+            ItemKind::Impl {
+                unsafety,
+                polarity,
+                defaultness,
+                constness,
+                generics: _,
+                of_trait: None,
+                self_ty: _,
+                items: _,
+            } => {
                 self.invalid_visibility(
                     &item.vis,
                     Some("place qualifiers on individual impl items instead"),
                 );
                 if unsafety == Unsafety::Unsafe {
-                    span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
+                    struct_span_err!(
+                        self.session,
+                        item.span,
+                        E0197,
+                        "inherent impls cannot be unsafe"
+                    )
+                    .emit();
                 }
                 if polarity == ImplPolarity::Negative {
                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
@@ -602,6 +676,12 @@
                         .note("only trait implementations may be annotated with default")
                         .emit();
                 }
+                if constness == Constness::Const {
+                    self.err_handler()
+                        .struct_span_err(item.span, "inherent impls cannot be `const`")
+                        .note("only trait implementations may be annotated with `const`")
+                        .emit();
+                }
             }
             ItemKind::Fn(ref sig, ref generics, _) => {
                 self.visit_fn_header(&sig.header);
@@ -678,6 +758,18 @@
                     }
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
+
+                // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
+                // context for the supertraits.
+                self.visit_vis(&item.vis);
+                self.visit_ident(item.ident);
+                self.visit_generics(generics);
+                self.with_bound_context(BoundContext::TraitBounds, |this| {
+                    walk_list!(this, visit_param_bound, bounds);
+                });
+                walk_list!(self, visit_trait_item, trait_items);
+                walk_list!(self, visit_attribute, &item.attrs);
+                return;
             }
             ItemKind::Mod(_) => {
                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
@@ -822,14 +914,38 @@
         visit::walk_generic_param(self, param);
     }
 
+    fn visit_param_bound(&mut self, bound: &'a GenericBound) {
+        match bound {
+            GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
+                if let Some(ctx) = self.bound_context {
+                    let msg = format!("`?const` is not permitted in {}", ctx.description());
+                    self.err_handler().span_err(bound.span(), &msg);
+                }
+            }
+
+            GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
+                self.err_handler()
+                    .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
+            }
+
+            _ => {}
+        }
+
+        visit::walk_param_bound(self, bound)
+    }
+
     fn visit_pat(&mut self, pat: &'a Pat) {
         match pat.kind {
             PatKind::Lit(ref expr) => {
                 self.check_expr_within_pat(expr, false);
             }
             PatKind::Range(ref start, ref end, _) => {
-                self.check_expr_within_pat(start, true);
-                self.check_expr_within_pat(end, true);
+                if let Some(expr) = start {
+                    self.check_expr_within_pat(expr, true);
+                }
+                if let Some(expr) = end {
+                    self.check_expr_within_pat(expr, true);
+                }
             }
             _ => {}
         }
@@ -896,7 +1012,7 @@
                 Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
                     if mut_ident {
                         self.lint_buffer.buffer_lint(
-                            lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                            PATTERNS_IN_FNS_WITHOUT_BODY,
                             ti.id,
                             span,
                             "patterns aren't allowed in methods without bodies",
@@ -925,11 +1041,12 @@
     }
 }
 
-pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
+pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
     let mut validator = AstValidator {
         session,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
+        bound_context: None,
         is_impl_trait_banned: false,
         is_assoc_ty_bound_banned: false,
         lint_buffer: lints,
diff --git a/src/libsyntax/feature_gate/check.rs b/src/librustc_ast_passes/feature_gate.rs
similarity index 68%
rename from src/libsyntax/feature_gate/check.rs
rename to src/librustc_ast_passes/feature_gate.rs
index 0e94a72..9531274 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -1,51 +1,31 @@
-use crate::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use crate::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
-use crate::attr;
-use crate::sess::ParseSess;
-use crate::visit::{self, FnKind, Visitor};
-
-use errors::{Applicability, DiagnosticBuilder, Handler};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_error_codes::*;
-use rustc_feature::{find_feature_issue, GateIssue};
+use rustc_errors::{struct_span_err, Handler};
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
-use rustc_feature::{Feature, Features, State as FeatureState, UnstableFeatures};
-use rustc_feature::{
-    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
-};
-use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_feature::{Features, GateIssue, UnstableFeatures};
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
+use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
+use syntax::attr;
+use syntax::sess::{feature_err, feature_err_issue, ParseSess};
+use syntax::visit::{self, FnKind, Visitor};
 
 use log::debug;
 
 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);
+    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
+        let (cx, has_feature, span, name, explain) = (&*$cx, $has_feature, $span, $name, $explain);
         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) {
-            leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
-                .emit();
+            feature_err_issue(cx.parse_sess, name, span, GateIssue::Language, explain).emit();
         }
     }};
 }
 
-macro_rules! gate_feature {
+macro_rules! gate_feature_post {
     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
-        gate_feature_fn!(
-            $cx,
-            |x: &Features| x.$feature,
-            $span,
-            sym::$feature,
-            $explain,
-            GateStrength::Hard
-        )
-    };
-    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
-        gate_feature_fn!($cx, |x: &Features| x.$feature, $span, sym::$feature, $explain, $level)
+        gate_feature_fn!($cx, |x: &Features| x.$feature, $span, sym::$feature, $explain)
     };
 }
 
@@ -53,92 +33,11 @@
     PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
 }
 
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum GateStrength {
-    /// A hard error. (Most feature gates should use this.)
-    Hard,
-    /// Only a warning. (Use this only as backwards-compatibility demands.)
-    Soft,
-}
-
-pub fn feature_err<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    explain: &str,
-) -> DiagnosticBuilder<'a> {
-    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
-}
-
-pub fn feature_err_issue<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    issue: GateIssue,
-    explain: &str,
-) -> DiagnosticBuilder<'a> {
-    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
-}
-
-fn leveled_feature_err<'a>(
-    sess: &'a ParseSess,
-    feature: Symbol,
-    span: impl Into<MultiSpan>,
-    issue: GateIssue,
-    explain: &str,
-    level: GateStrength,
-) -> DiagnosticBuilder<'a> {
-    let diag = &sess.span_diagnostic;
-
-    let mut err = match level {
-        GateStrength::Hard => {
-            diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658))
-        }
-        GateStrength::Soft => diag.struct_span_warn(span, explain),
-    };
-
-    if let Some(n) = find_feature_issue(feature, issue) {
-        err.note(&format!(
-            "for more information, see https://github.com/rust-lang/rust/issues/{}",
-            n,
-        ));
-    }
-
-    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
-    if sess.unstable_features.is_nightly_build() {
-        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
-    }
-
-    // If we're on stable and only emitting a "soft" warning, add a note to
-    // clarify that the feature isn't "on" (rather than being on but
-    // warning-worthy).
-    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
-        err.help("a nightly build of the compiler is required to enable this feature");
-    }
-
-    err
-}
-
 struct PostExpansionVisitor<'a> {
     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, $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, $feature, span, $explain, $level)
-        }
-    }};
-}
-
 impl<'a> PostExpansionVisitor<'a> {
     fn check_abi(&self, abi: ast::StrLit) {
         let ast::StrLit { symbol_unescaped, span, .. } = abi;
@@ -330,7 +229,7 @@
             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);
+            gate_feature_fn!(self, has_feature, attr.span, name, descr);
         }
         // Check unstable flavors of the `#[doc]` attribute.
         if attr.check_name(sym::doc) {
@@ -338,7 +237,7 @@
                 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_feature_post!(self, $feature, attr.span, msg);
                     })*
                 }}
 
@@ -439,7 +338,7 @@
                 }
             }
 
-            ast::ItemKind::Impl(_, polarity, defaultness, ..) => {
+            ast::ItemKind::Impl { polarity, defaultness, .. } => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(
                         &self,
@@ -513,7 +412,7 @@
                 self.check_extern(bare_fn_ty.ext);
             }
             ast::TyKind::Never => {
-                gate_feature_post!(&self, never_type, ty.span, "The `!` type is experimental");
+                gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
             }
             _ => {}
         }
@@ -570,29 +469,8 @@
         visit::walk_expr(self, e)
     }
 
-    fn visit_arm(&mut self, arm: &'a ast::Arm) {
-        visit::walk_arm(self, arm)
-    }
-
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match &pattern.kind {
-            PatKind::Slice(pats) => {
-                for pat in &*pats {
-                    let span = pat.span;
-                    let inner_pat = match &pat.kind {
-                        PatKind::Ident(.., Some(pat)) => pat,
-                        _ => pat,
-                    };
-                    if inner_pat.is_rest() {
-                        gate_feature_post!(
-                            &self,
-                            slice_patterns,
-                            span,
-                            "subslice patterns are unstable"
-                        );
-                    }
-                }
-            }
             PatKind::Box(..) => {
                 gate_feature_post!(
                     &self,
@@ -726,173 +604,6 @@
     }
 }
 
-pub fn get_features(
-    span_handler: &Handler,
-    krate_attrs: &[ast::Attribute],
-    crate_edition: Edition,
-    allow_features: &Option<Vec<String>>,
-) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
-        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
-        err.span_label(span, "feature has been removed");
-        if let Some(reason) = reason {
-            err.note(reason);
-        }
-        err.emit();
-    }
-
-    let mut features = Features::default();
-    let mut edition_enabled_features = FxHashMap::default();
-
-    for &edition in ALL_EDITIONS {
-        if edition <= crate_edition {
-            // The `crate_edition` implies its respective umbrella feature-gate
-            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
-            edition_enabled_features.insert(edition.feature_name(), edition);
-        }
-    }
-
-    for feature in active_features_up_to(crate_edition) {
-        feature.set(&mut features, DUMMY_SP);
-        edition_enabled_features.insert(feature.name, crate_edition);
-    }
-
-    // Process the edition umbrella feature-gates first, to ensure
-    // `edition_enabled_features` is completed before it's queried.
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        for mi in list {
-            if !mi.is_word() {
-                continue;
-            }
-
-            let name = mi.name_or_empty();
-
-            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
-            if let Some(edition) = edition {
-                if edition <= crate_edition {
-                    continue;
-                }
-
-                for feature in active_features_up_to(edition) {
-                    // FIXME(Manishearth) there is currently no way to set
-                    // lib features by edition
-                    feature.set(&mut features, DUMMY_SP);
-                    edition_enabled_features.insert(feature.name, edition);
-                }
-            }
-        }
-    }
-
-    for attr in krate_attrs {
-        if !attr.check_name(sym::feature) {
-            continue;
-        }
-
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => continue,
-        };
-
-        let bad_input = |span| {
-            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
-        };
-
-        for mi in list {
-            let name = match mi.ident() {
-                Some(ident) if mi.is_word() => ident.name,
-                Some(ident) => {
-                    bad_input(mi.span())
-                        .span_suggestion(
-                            mi.span(),
-                            "expected just one word",
-                            format!("{}", ident.name),
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
-                    continue;
-                }
-                None => {
-                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
-                    continue;
-                }
-            };
-
-            if let Some(edition) = edition_enabled_features.get(&name) {
-                struct_span_warn!(
-                    span_handler,
-                    mi.span(),
-                    E0705,
-                    "the feature `{}` is included in the Rust {} edition",
-                    name,
-                    edition,
-                )
-                .emit();
-                continue;
-            }
-
-            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
-                // Handled in the separate loop above.
-                continue;
-            }
-
-            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
-            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
-            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
-                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
-                    state
-                {
-                    feature_removed(span_handler, mi.span(), *reason);
-                    continue;
-                }
-            }
-
-            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
-                let since = Some(Symbol::intern(since));
-                features.declared_lang_features.push((name, mi.span(), since));
-                continue;
-            }
-
-            if let Some(allowed) = allow_features.as_ref() {
-                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
-                    span_err!(
-                        span_handler,
-                        mi.span(),
-                        E0725,
-                        "the feature `{}` is not in the list of allowed features",
-                        name
-                    );
-                    continue;
-                }
-            }
-
-            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
-                f.set(&mut features, mi.span());
-                features.declared_lang_features.push((name, mi.span(), None));
-                continue;
-            }
-
-            features.declared_lib_features.push((name, mi.span()));
-        }
-    }
-
-    features
-}
-
-fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
-    ACTIVE_FEATURES.iter().filter(move |feature| {
-        if let Some(feature_edition) = feature.edition { feature_edition <= edition } else { false }
-    })
-}
-
 pub fn check_crate(
     krate: &ast::Crate,
     parse_sess: &ParseSess,
@@ -906,7 +617,7 @@
     macro_rules! gate_all {
         ($gate:ident, $msg:literal) => {
             for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                gate_feature!(&visitor, $gate, *span, $msg);
+                gate_feature_post!(&visitor, $gate, *span, $msg);
             }
         };
     }
@@ -916,6 +627,9 @@
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
+    gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
+    gate_all!(const_trait_impl, "const trait impls are experimental");
+    gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
@@ -925,7 +639,7 @@
             // disabling these uses of early feature-gatings.
             if false {
                 for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                    gate_feature!(&visitor, $gate, *span, $msg);
+                    gate_feature_post!(&visitor, $gate, *span, $msg);
                 }
             }
         };
@@ -953,13 +667,14 @@
 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) {
     if !unstable.is_nightly_build() {
         for attr in krate.attrs.iter().filter(|attr| attr.check_name(sym::feature)) {
-            span_err!(
+            struct_span_err!(
                 span_handler,
                 attr.span,
                 E0554,
                 "`#![feature]` may not be used on the {} release channel",
                 option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
-            );
+            )
+            .emit();
         }
     }
 }
diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs
new file mode 100644
index 0000000..5de45f4
--- /dev/null
+++ b/src/librustc_ast_passes/lib.rs
@@ -0,0 +1,9 @@
+//! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
+//! parsed by `rustc_parse` and then lowered, after the passes in this crate,
+//! by `rustc_ast_lowering`.
+
+#![cfg_attr(bootstrap, feature(slice_patterns))]
+
+pub mod ast_validation;
+pub mod feature_gate;
+pub mod show_span;
diff --git a/src/libsyntax/show_span.rs b/src/librustc_ast_passes/show_span.rs
similarity index 88%
rename from src/libsyntax/show_span.rs
rename to src/librustc_ast_passes/show_span.rs
index fb64123..4596e8f 100644
--- a/src/libsyntax/show_span.rs
+++ b/src/librustc_ast_passes/show_span.rs
@@ -5,9 +5,9 @@
 
 use std::str::FromStr;
 
-use crate::ast;
-use crate::visit;
-use crate::visit::Visitor;
+use syntax::ast;
+use syntax::visit;
+use syntax::visit::Visitor;
 
 enum Mode {
     Expression,
@@ -29,7 +29,7 @@
 }
 
 struct ShowSpanVisitor<'a> {
-    span_diagnostic: &'a errors::Handler,
+    span_diagnostic: &'a rustc_errors::Handler,
     mode: Mode,
 }
 
@@ -60,7 +60,7 @@
     }
 }
 
-pub fn run(span_diagnostic: &errors::Handler, mode: &str, krate: &ast::Crate) {
+pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) {
     let mode = match mode.parse().ok() {
         Some(mode) => mode,
         None => return,
diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml
index f56cc93..3ce7f5d 100644
--- a/src/librustc_builtin_macros/Cargo.toml
+++ b/src/librustc_builtin_macros/Cargo.toml
@@ -10,15 +10,15 @@
 doctest = false
 
 [dependencies]
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 fmt_macros = { path = "../libfmt_macros" }
 log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_target = { path = "../librustc_target" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index a136a07..4723544 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -2,7 +2,7 @@
 //
 use State::*;
 
-use errors::{DiagnosticBuilder, PResult};
+use rustc_errors::{struct_span_err, DiagnosticBuilder, PResult};
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -11,9 +11,6 @@
 use syntax::ptr::P;
 use syntax::token::{self, Token};
 use syntax::tokenstream::{self, TokenStream};
-use syntax::{span_err, struct_span_err};
-
-use rustc_error_codes::*;
 
 enum State {
     Asm,
@@ -173,12 +170,13 @@
                         Some('=') => None,
                         Some('+') => Some(Symbol::intern(&format!("={}", ch.as_str()))),
                         _ => {
-                            span_err!(
-                                cx,
+                            struct_span_err!(
+                                cx.parse_sess.span_diagnostic,
                                 span,
                                 E0661,
                                 "output operand constraint lacks '=' or '+'"
-                            );
+                            )
+                            .emit();
                             None
                         }
                     };
@@ -202,9 +200,21 @@
                     let constraint = parse_asm_str(&mut p)?;
 
                     if constraint.as_str().starts_with("=") {
-                        span_err!(cx, p.prev_span, E0662, "input operand constraint contains '='");
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
+                            p.prev_span,
+                            E0662,
+                            "input operand constraint contains '='"
+                        )
+                        .emit();
                     } else if constraint.as_str().starts_with("+") {
-                        span_err!(cx, p.prev_span, E0663, "input operand constraint contains '+'");
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
+                            p.prev_span,
+                            E0663,
+                            "input operand constraint contains '+'"
+                        )
+                        .emit();
                     }
 
                     p.expect(&token::OpenDelim(token::Paren))?;
@@ -225,12 +235,13 @@
                     if OPTIONS.iter().any(|&opt| s == opt) {
                         cx.span_warn(p.prev_span, "expected a clobber, found an option");
                     } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") {
-                        span_err!(
-                            cx,
+                        struct_span_err!(
+                            cx.parse_sess.span_diagnostic,
                             p.prev_span,
                             E0664,
                             "clobber should not be surrounded by braces"
-                        );
+                        )
+                        .emit();
                     }
 
                     clobs.push(s);
diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs
index 9043db4..a992b6e 100644
--- a/src/librustc_builtin_macros/assert.rs
+++ b/src/librustc_builtin_macros/assert.rs
@@ -1,4 +1,4 @@
-use errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 
 use rustc_expand::base::*;
 use rustc_parse::parser::Parser;
@@ -106,7 +106,7 @@
     let custom_message =
         if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
             let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal");
-            let comma_span = cx.source_map().next_point(parser.prev_span);
+            let comma_span = parser.prev_span.shrink_to_hi();
             err.span_suggestion_short(
                 comma_span,
                 "try adding a comma",
diff --git a/src/librustc_builtin_macros/cfg.rs b/src/librustc_builtin_macros/cfg.rs
index 62a4dc0..cee62a5 100644
--- a/src/librustc_builtin_macros/cfg.rs
+++ b/src/librustc_builtin_macros/cfg.rs
@@ -1,8 +1,8 @@
-/// The compiler code necessary to support the cfg! extension, which expands to
-/// a literal `true` or `false` based on whether the given cfg matches the
-/// current compilation environment.
-use errors::DiagnosticBuilder;
+//! The compiler code necessary to support the cfg! extension, which expands to
+//! a literal `true` or `false` based on whether the given cfg matches the
+//! current compilation environment.
 
+use rustc_errors::DiagnosticBuilder;
 use rustc_expand::base::{self, *};
 use rustc_span::Span;
 use syntax::ast;
diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs
index f40d6d7..b4f059e 100644
--- a/src/librustc_builtin_macros/deriving/default.rs
+++ b/src/librustc_builtin_macros/deriving/default.rs
@@ -2,14 +2,12 @@
 use crate::deriving::generic::*;
 use crate::deriving::path_std;
 
+use rustc_errors::struct_span_err;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use syntax::ast::{Expr, MetaItem};
 use syntax::ptr::P;
-use syntax::span_err;
-
-use rustc_error_codes::*;
 
 pub fn expand_deriving_default(
     cx: &mut ExtCtxt<'_>,
@@ -74,7 +72,13 @@
             }
         },
         StaticEnum(..) => {
-            span_err!(cx, trait_span, E0665, "`Default` cannot be derived for enums, only structs");
+            struct_span_err!(
+                cx.parse_sess.span_diagnostic,
+                trait_span,
+                E0665,
+                "`Default` cannot be derived for enums, only structs"
+            )
+            .emit();
             // let compilation continue
             DummyResult::raw_expr(trait_span, true)
         }
diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs
index 7092483..f891801 100644
--- a/src/librustc_builtin_macros/deriving/generic/mod.rs
+++ b/src/librustc_builtin_macros/deriving/generic/mod.rs
@@ -705,15 +705,16 @@
             self.span,
             Ident::invalid(),
             a,
-            ast::ItemKind::Impl(
+            ast::ItemKind::Impl {
                 unsafety,
-                ast::ImplPolarity::Positive,
-                ast::Defaultness::Final,
-                trait_generics,
-                opt_trait_ref,
-                self_type,
-                methods.into_iter().chain(associated_types).collect(),
-            ),
+                polarity: ast::ImplPolarity::Positive,
+                defaultness: ast::Defaultness::Final,
+                constness: ast::Constness::NotConst,
+                generics: trait_generics,
+                of_trait: opt_trait_ref,
+                self_ty: self_type,
+                items: methods.into_iter().chain(associated_types).collect(),
+            },
         )
     }
 
@@ -1608,7 +1609,7 @@
                 } else {
                     ast::BindingMode::ByRef(mutbl)
                 };
-                cx.pat(path.span, PatKind::Ident(binding_mode, (*path).clone(), None))
+                cx.pat(path.span, PatKind::Ident(binding_mode, *path, None))
             })
             .collect()
     }
diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs
index 4d83a66..914dcdf 100644
--- a/src/librustc_builtin_macros/deriving/mod.rs
+++ b/src/librustc_builtin_macros/deriving/mod.rs
@@ -156,15 +156,16 @@
         span,
         ast::Ident::invalid(),
         attrs,
-        ItemKind::Impl(
-            ast::Unsafety::Normal,
-            ast::ImplPolarity::Positive,
-            ast::Defaultness::Final,
+        ItemKind::Impl {
+            unsafety: ast::Unsafety::Normal,
+            polarity: ast::ImplPolarity::Positive,
+            defaultness: ast::Defaultness::Final,
+            constness: ast::Constness::NotConst,
             generics,
-            Some(trait_ref),
-            self_type,
-            Vec::new(),
-        ),
+            of_trait: Some(trait_ref),
+            self_ty: self_type,
+            items: Vec::new(),
+        },
     );
 
     push(Annotatable::Item(newitem));
diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs
index e2662fa..3f4e24c 100644
--- a/src/librustc_builtin_macros/format.rs
+++ b/src/librustc_builtin_macros/format.rs
@@ -3,10 +3,8 @@
 
 use fmt_macros as parse;
 
-use errors::pluralize;
-use errors::Applicability;
-use errors::DiagnosticBuilder;
-
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
@@ -15,7 +13,6 @@
 use syntax::token;
 use syntax::tokenstream::TokenStream;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 
@@ -593,17 +590,6 @@
             parse::NextArgument(ref arg) => {
                 // Build the position
                 let pos = {
-                    let pos = |c, arg| {
-                        let mut path = Context::rtpath(self.ecx, "Position");
-                        path.push(self.ecx.ident_of(c, sp));
-                        match arg {
-                            Some(i) => {
-                                let arg = self.ecx.expr_usize(sp, i);
-                                self.ecx.expr_call_global(sp, path, vec![arg])
-                            }
-                            None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
-                        }
-                    };
                     match arg.position {
                         parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => {
                             // Map to index in final generated argument array
@@ -618,7 +604,7 @@
                                     arg_idx
                                 }
                             };
-                            pos("At", Some(arg_idx))
+                            self.ecx.expr_usize(sp, arg_idx)
                         }
 
                         // should never be the case, because names are already
diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs
index 2bcd76e..052e62e 100644
--- a/src/librustc_builtin_macros/global_asm.rs
+++ b/src/librustc_builtin_macros/global_asm.rs
@@ -1,14 +1,14 @@
-/// Module-level assembly support.
-///
-/// The macro defined here allows you to specify "top-level",
-/// "file-scoped", or "module-level" assembly. These synonyms
-/// all correspond to LLVM's module-level inline assembly instruction.
-///
-/// For example, `global_asm!("some assembly here")` codegens to
-/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
-/// therefore apply.
-use errors::DiagnosticBuilder;
+//! Module-level assembly support.
+//!
+//! The macro defined here allows you to specify "top-level",
+//! "file-scoped", or "module-level" assembly. These synonyms
+//! all correspond to LLVM's module-level inline assembly instruction.
+//!
+//! For example, `global_asm!("some assembly here")` codegens to
+//! LLVM's `module asm "some assembly here"`. All of LLVM's caveats
+//! therefore apply.
 
+use rustc_errors::DiagnosticBuilder;
 use rustc_expand::base::{self, *};
 use rustc_span::source_map::respan;
 use rustc_span::Span;
diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs
index 44968d6..ae70608 100644
--- a/src/librustc_builtin_macros/proc_macro_harness.rs
+++ b/src/librustc_builtin_macros/proc_macro_harness.rs
@@ -40,7 +40,7 @@
 struct CollectProcMacros<'a> {
     macros: Vec<ProcMacro>,
     in_root: bool,
-    handler: &'a errors::Handler,
+    handler: &'a rustc_errors::Handler,
     is_proc_macro_crate: bool,
     is_test_crate: bool,
 }
@@ -53,7 +53,7 @@
     has_proc_macro_decls: bool,
     is_test_crate: bool,
     num_crate_types: usize,
-    handler: &errors::Handler,
+    handler: &rustc_errors::Handler,
 ) -> ast::Crate {
     let ecfg = ExpansionConfig::default("proc_macro".to_string());
     let mut cx = ExtCtxt::new(sess, ecfg, resolver);
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index 19a766d..dc85a92 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -1,15 +1,15 @@
 use rustc_expand::base::{self, *};
 use rustc_expand::panictry;
 use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
+use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
+use rustc_span::{self, Pos, Span};
 use syntax::ast;
-use syntax::early_buffered_lints::INCOMPLETE_INCLUDE;
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::token;
 use syntax::tokenstream::TokenStream;
 
-use rustc_span::{self, Pos, Span};
 use smallvec::SmallVec;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs
index 0eee212..07715cd 100644
--- a/src/librustc_builtin_macros/test.rs
+++ b/src/librustc_builtin_macros/test.rs
@@ -325,7 +325,7 @@
                              `expected = \"error message\"`",
                         )
                         .note(
-                            "Errors in this attribute were erroneously \
+                            "errors in this attribute were erroneously \
                                 allowed and will become a hard error in a \
                                 future release.",
                         )
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index eddf492..17d180d 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -40,7 +40,7 @@
     resolver: &mut dyn Resolver,
     should_test: bool,
     krate: &mut ast::Crate,
-    span_diagnostic: &errors::Handler,
+    span_diagnostic: &rustc_errors::Handler,
     features: &Features,
     panic_strategy: PanicStrategy,
     platform_panic_strategy: PanicStrategy,
@@ -351,7 +351,7 @@
     attr::contains_name(&i.attrs, sym::rustc_test_marker)
 }
 
-fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
+fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
     let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
     test_attr.meta_item_list().map(|meta_list| {
         if meta_list.len() != 1 {
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index 2d9232b..dd9eadd 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -28,8 +28,8 @@
 rustc_index = { path = "../librustc_index" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_session = { path = "../librustc_session" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
-rustc_expand = { path = "../librustc_expand" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 4ed4e8a..fc1b365 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -246,7 +246,7 @@
     }
 
     // FIXME(eddyb) consolidate these two `inline` calls (and avoid overwrites).
-    if instance.def.is_inline(cx.tcx) {
+    if instance.def.requires_inline(cx.tcx) {
         inline(cx, llfn, attributes::InlineAttr::Hint);
     }
 
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 3134ae5..b5895b5 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -120,12 +120,13 @@
                 info!("adding bytecode {}", name);
                 let bc_encoded = data.data();
 
-                let (bc, id) = cgcx.prof.generic_pass(&format!("decode {}", name)).run(|| {
-                    match DecodedBytecode::new(bc_encoded) {
+                let (bc, id) = cgcx
+                    .prof
+                    .extra_verbose_generic_activity(&format!("decode {}", name))
+                    .run(|| match DecodedBytecode::new(bc_encoded) {
                         Ok(b) => Ok((b.bytecode(), b.identifier().to_string())),
                         Err(e) => Err(diag_handler.fatal(&e)),
-                    }
-                })?;
+                    })?;
                 let bc = SerializedModule::FromRlib(bc);
                 upstream_modules.push((bc, CString::new(id).unwrap()));
             }
@@ -280,8 +281,9 @@
         // save and persist everything with the original module.
         let mut linker = Linker::new(llmod);
         for (bc_decoded, name) in serialized_modules {
+            let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module");
             info!("linking {:?}", name);
-            cgcx.prof.generic_pass(&format!("ll link {:?}", name)).run(|| {
+            cgcx.prof.extra_verbose_generic_activity(&format!("ll link {:?}", name)).run(|| {
                 let data = bc_decoded.data();
                 linker.add(&data).map_err(|()| {
                     let msg = format!("failed to load bc of {:?}", name);
@@ -633,7 +635,7 @@
         }
 
         cgcx.prof
-            .generic_pass("LTO passes")
+            .extra_verbose_generic_activity("LTO_passes")
             .run(|| llvm::LLVMRunPassManager(pm, module.module_llvm.llmod()));
 
         llvm::LLVMDisposePassManager(pm);
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index afdfb36..4be7b84 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -424,13 +424,23 @@
 
         // Finally, run the actual optimization passes
         {
+            let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes");
             let desc = &format!("llvm function passes [{}]", module_name.unwrap());
-            let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None };
+            let _timer = if config.time_module {
+                Some(cgcx.prof.extra_verbose_generic_activity(desc))
+            } else {
+                None
+            };
             llvm::LLVMRustRunFunctionPassManager(fpm, llmod);
         }
         {
+            let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes");
             let desc = &format!("llvm module passes [{}]", module_name.unwrap());
-            let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None };
+            let _timer = if config.time_module {
+                Some(cgcx.prof.extra_verbose_generic_activity(desc))
+            } else {
+                None
+            };
             llvm::LLVMRunPassManager(mpm, llmod);
         }
 
@@ -556,7 +566,11 @@
 
         {
             let desc = &format!("codegen passes [{}]", module_name.unwrap());
-            let _timer = if config.time_module { Some(cgcx.prof.generic_pass(desc)) } else { None };
+            let _timer = if config.time_module {
+                Some(cgcx.prof.extra_verbose_generic_activity(desc))
+            } else {
+                None
+            };
 
             if config.emit_ir {
                 let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir");
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index cb44a56..d3b524c 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -13,7 +13,7 @@
 //!   but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int,
 //!   int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
 
-use super::{LlvmCodegenBackend, ModuleLlvm};
+use super::ModuleLlvm;
 
 use crate::builder::Builder;
 use crate::common;
@@ -29,7 +29,6 @@
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::session::config::DebugInfo;
 use rustc::ty::TyCtxt;
-use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm;
 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::*;
@@ -100,8 +99,7 @@
 pub fn compile_codegen_unit(
     tcx: TyCtxt<'tcx>,
     cgu_name: Symbol,
-    tx_to_llvm_workers: &std::sync::mpsc::Sender<Box<dyn std::any::Any + Send>>,
-) {
+) -> (ModuleCodegen<ModuleLlvm>, u64) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
     let start_time = Instant::now();
 
@@ -115,8 +113,6 @@
     // the time we needed for codegenning it.
     let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
 
-    submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tx_to_llvm_workers, module, cost);
-
     fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
@@ -164,6 +160,8 @@
             kind: ModuleKind::Regular,
         }
     }
+
+    (module, cost)
 }
 
 pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index 78dd6fc..04d9214 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -130,12 +130,7 @@
                     } else {
                         // This is a monomorphization of a generic function
                         // defined in an upstream crate.
-                        if cx
-                            .tcx
-                            .upstream_monomorphizations_for(instance_def_id)
-                            .map(|set| set.contains_key(instance.substs))
-                            .unwrap_or(false)
-                        {
+                        if instance.upstream_monomorphization(tcx).is_some() {
                             // This is instantiated in another crate. It cannot
                             // be `hidden`.
                         } else {
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index f07601e..50a35fe 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -143,6 +143,10 @@
     data_layout.replace("-Fi8-", "-")
 }
 
+fn strip_x86_address_spaces(data_layout: String) -> String {
+    data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-")
+}
+
 pub unsafe fn create_module(
     tcx: TyCtxt<'_>,
     llcx: &'ll llvm::Context,
@@ -156,6 +160,11 @@
     if llvm_util::get_major_version() < 9 {
         target_data_layout = strip_function_ptr_alignment(target_data_layout);
     }
+    if llvm_util::get_major_version() < 10 {
+        if sess.target.target.arch == "x86" || sess.target.target.arch == "x86_64" {
+            target_data_layout = strip_x86_address_spaces(target_data_layout);
+        }
+    }
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 8d8e86d..d1f70ad 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -1286,9 +1286,9 @@
     let generator_layout = body.generator_layout.as_ref().unwrap();
     let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
 
-    let state_arg = mir::PlaceBase::Local(mir::Local::new(1));
+    let state_arg = mir::Local::new(1);
     for var in &body.var_debug_info {
-        if var.place.base != state_arg {
+        if var.place.local != state_arg {
             continue;
         }
         match var.place.projection[..] {
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 8ea50a9..031837c 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -922,6 +922,9 @@
         //      #include <stdint.h>
         //
         //      struct rust_panic {
+        //          rust_panic(const rust_panic&);
+        //          ~rust_panic();
+        //
         //          uint64_t x[2];
         //      }
         //
@@ -929,17 +932,19 @@
         //          try {
         //              foo();
         //              return 0;
-        //          } catch(rust_panic a) {
+        //          } catch(rust_panic& a) {
         //              ret[0] = a.x[0];
         //              ret[1] = a.x[1];
+        //              a.x[0] = 0;
         //              return 1;
         //          }
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
         let i64_2 = bx.type_array(bx.type_i64(), 2);
-        let i64_align = bx.tcx().data_layout.i64_align.abi;
-        let slot = bx.alloca(i64_2, i64_align);
+        let i64_2_ptr = bx.type_ptr_to(i64_2);
+        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
+        let slot = bx.alloca(i64_2_ptr, ptr_align);
         bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
 
         normal.ret(bx.const_i32(0));
@@ -947,15 +952,31 @@
         let cs = catchswitch.catch_switch(None, None, 1);
         catchswitch.add_handler(cs, catchpad.llbb());
 
+        // The flag value of 8 indicates that we are catching the exception by
+        // reference instead of by value. We can't use catch by value because
+        // that requires copying the exception object, which we don't support
+        // since our exception object effectively contains a Box.
+        //
+        // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
+        let flags = bx.const_i32(8);
         let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
             Some(did) => bx.get_static(did),
             None => bug!("eh_catch_typeinfo not defined, but needed for SEH unwinding"),
         };
-        let funclet = catchpad.catch_pad(cs, &[tydesc, bx.const_i32(0), slot]);
+        let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]);
 
-        let payload = catchpad.load(slot, i64_align);
+        let i64_align = bx.tcx().data_layout.i64_align.abi;
+        let payload_ptr = catchpad.load(slot, ptr_align);
+        let payload = catchpad.load(payload_ptr, i64_align);
         let local_ptr = catchpad.bitcast(local_ptr, bx.type_ptr_to(i64_2));
         catchpad.store(payload, local_ptr, i64_align);
+
+        // Clear the first word of the exception so avoid double-dropping it.
+        // This will be read by the destructor which is implicitly called at the
+        // end of the catch block by the runtime.
+        let payload_0_ptr = catchpad.inbounds_gep(payload_ptr, &[bx.const_i32(0), bx.const_i32(0)]);
+        catchpad.store(bx.const_u64(0), payload_0_ptr, i64_align);
+
         catchpad.catch_ret(&funclet, caught.llbb());
 
         caught.ret(bx.const_i32(1));
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 349cff7..70e3874 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -19,6 +19,7 @@
 #![feature(link_args)]
 #![feature(static_nobundle)]
 #![feature(trusted_len)]
+#![recursion_limit = "256"]
 
 use back::write::{create_informational_target_machine, create_target_machine};
 use rustc_span::symbol::Symbol;
@@ -32,6 +33,7 @@
 use rustc_errors::{FatalError, Handler};
 use std::any::Any;
 use std::ffi::CStr;
+use std::fs;
 use std::sync::Arc;
 use syntax::expand::allocator::AllocatorKind;
 
@@ -43,6 +45,7 @@
 use rustc::util::common::ErrorReported;
 use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_serialize::json;
 
 mod back {
     pub mod archive;
@@ -108,9 +111,8 @@
         &self,
         tcx: TyCtxt<'_>,
         cgu_name: Symbol,
-        tx: &std::sync::mpsc::Sender<Box<dyn Any + Send>>,
-    ) {
-        base::compile_codegen_unit(tcx, cgu_name, tx);
+    ) -> (ModuleCodegen<ModuleLlvm>, u64) {
+        base::compile_codegen_unit(tcx, cgu_name)
     }
     fn target_machine_factory(
         &self,
@@ -283,7 +285,7 @@
             rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results);
         }
 
-        sess.time("serialize work products", move || {
+        sess.time("serialize_work_products", move || {
             rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
         });
 
@@ -298,9 +300,21 @@
             return Ok(());
         }
 
+        if sess.opts.debugging_opts.no_link {
+            // FIXME: use a binary format to encode the `.rlink` file
+            let rlink_data = json::encode(&codegen_results).map_err(|err| {
+                sess.fatal(&format!("failed to encode rlink: {}", err));
+            })?;
+            let rlink_file = outputs.with_extension("rlink");
+            fs::write(&rlink_file, rlink_data).map_err(|err| {
+                sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
+            })?;
+            return Ok(());
+        }
+
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        sess.time("linking", || {
+        sess.time("link_crate", || {
             use crate::back::archive::LlvmArchiveBuilder;
             use rustc_codegen_ssa::back::link::link_binary;
 
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index b3c58b2..4823fe1 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -46,7 +46,7 @@
 }
 
 unsafe fn configure_llvm(sess: &Session) {
-    let n_args = sess.opts.cg.llvm_args.len();
+    let n_args = sess.opts.cg.llvm_args.len() + sess.target.target.options.llvm_args.len();
     let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
     let mut llvm_args = Vec::with_capacity(n_args + 1);
 
@@ -56,14 +56,12 @@
         full_arg.trim().split(|c: char| c == '=' || c.is_whitespace()).next().unwrap_or("")
     }
 
-    let user_specified_args: FxHashSet<_> = sess
-        .opts
-        .cg
-        .llvm_args
-        .iter()
-        .map(|s| llvm_arg_to_arg_name(s))
-        .filter(|s| s.len() > 0)
-        .collect();
+    let cg_opts = sess.opts.cg.llvm_args.iter();
+    let tg_opts = sess.target.target.options.llvm_args.iter();
+    let sess_args = cg_opts.chain(tg_opts);
+
+    let user_specified_args: FxHashSet<_> =
+        sess_args.clone().map(|s| llvm_arg_to_arg_name(s)).filter(|s| s.len() > 0).collect();
 
     {
         // This adds the given argument to LLVM. Unless `force` is true
@@ -110,7 +108,7 @@
         // during inlining. Unfortunately these may block other optimizations.
         add("-preserve-alignment-assumptions-during-inlining=false", false);
 
-        for arg in &sess.opts.cg.llvm_args {
+        for arg in sess_args {
             add(&(*arg), true);
         }
     }
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index eb192b2..9f8b4e7 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -32,5 +32,4 @@
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
 rustc_target = { path = "../librustc_target" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index a53402e..f56a417 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -53,6 +53,7 @@
     crate_name: &str,
     target_cpu: &str,
 ) {
+    let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
@@ -71,9 +72,11 @@
             );
         }
 
-        for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
-            check_file_is_writeable(obj, sess);
-        }
+        sess.time("link_binary_check_files_are_writeable", || {
+            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+                check_file_is_writeable(obj, sess);
+            }
+        });
 
         let tmpdir = TempFileBuilder::new()
             .prefix("rustc")
@@ -84,6 +87,7 @@
             let out_filename = out_filename(sess, crate_type, outputs, crate_name);
             match crate_type {
                 config::CrateType::Rlib => {
+                    let _timer = sess.timer("link_rlib");
                     link_rlib::<B>(
                         sess,
                         codegen_results,
@@ -118,29 +122,34 @@
     }
 
     // Remove the temporary object file and metadata if we aren't saving temps
-    if !sess.opts.cg.save_temps {
-        if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) {
-            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+    sess.time("link_binary_remove_temps", || {
+        if !sess.opts.cg.save_temps {
+            if sess.opts.output_types.should_codegen()
+                && !preserve_objects_for_their_debuginfo(sess)
+            {
+                for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
+                    remove(sess, obj);
+                }
+            }
+            for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref())
+            {
                 remove(sess, obj);
             }
-        }
-        for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
-            remove(sess, obj);
-        }
-        if let Some(ref metadata_module) = codegen_results.metadata_module {
-            if let Some(ref obj) = metadata_module.object {
-                remove(sess, obj);
+            if let Some(ref metadata_module) = codegen_results.metadata_module {
+                if let Some(ref obj) = metadata_module.object {
+                    remove(sess, obj);
+                }
+            }
+            if let Some(ref allocator_module) = codegen_results.allocator_module {
+                if let Some(ref obj) = allocator_module.object {
+                    remove(sess, obj);
+                }
+                if let Some(ref bc) = allocator_module.bytecode_compressed {
+                    remove(sess, bc);
+                }
             }
         }
-        if let Some(ref allocator_module) = codegen_results.allocator_module {
-            if let Some(ref obj) = allocator_module.object {
-                remove(sess, obj);
-            }
-            if let Some(ref bc) = allocator_module.bytecode_compressed {
-                remove(sess, bc);
-            }
-        }
-    }
+    });
 }
 
 // The third parameter is for env vars, used on windows to set up the
@@ -531,6 +540,7 @@
 
     {
         let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu);
+        link_sanitizer_runtime(sess, crate_type, &mut *linker);
         link_args::<B>(
             &mut *linker,
             flavor,
@@ -577,7 +587,7 @@
     let mut i = 0;
     loop {
         i += 1;
-        prog = sess.time("running linker", || exec_linker(sess, &mut cmd, out_filename, tmpdir));
+        prog = sess.time("run_linker", || exec_linker(sess, &mut cmd, out_filename, tmpdir));
         let output = match prog {
             Ok(ref output) => output,
             Err(_) => break,
@@ -735,6 +745,47 @@
     }
 }
 
+fn link_sanitizer_runtime(sess: &Session, crate_type: config::CrateType, linker: &mut dyn Linker) {
+    let sanitizer = match &sess.opts.debugging_opts.sanitizer {
+        Some(s) => s,
+        None => return,
+    };
+
+    if crate_type != config::CrateType::Executable {
+        return;
+    }
+
+    let name = match sanitizer {
+        Sanitizer::Address => "asan",
+        Sanitizer::Leak => "lsan",
+        Sanitizer::Memory => "msan",
+        Sanitizer::Thread => "tsan",
+    };
+
+    let default_sysroot = filesearch::get_or_default_sysroot();
+    let default_tlib =
+        filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple());
+
+    match sess.opts.target_triple.triple() {
+        "x86_64-apple-darwin" => {
+            // On Apple platforms, the sanitizer is always built as a dylib, and
+            // LLVM will link to `@rpath/*.dylib`, so we need to specify an
+            // rpath to the library as well (the rpath should be absolute, see
+            // PR #41352 for details).
+            let libname = format!("rustc_rt.{}", name);
+            let rpath = default_tlib.to_str().expect("non-utf8 component in path");
+            linker.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]);
+            linker.link_dylib(Symbol::intern(&libname));
+        }
+        "x86_64-unknown-linux-gnu" | "x86_64-fuchsia" | "aarch64-fuchsia" => {
+            let filename = format!("librustc_rt.{}.a", name);
+            let path = default_tlib.join(&filename);
+            linker.link_whole_rlib(&path);
+        }
+        _ => {}
+    }
+}
+
 /// Returns a boolean indicating whether the specified crate should be ignored
 /// during LTO.
 ///
@@ -1415,12 +1466,6 @@
             _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
                 add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
             }
-            _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum)
-                && crate_type == config::CrateType::Executable =>
-            {
-                // Link the sanitizer runtimes only if we are actually producing an executable
-                link_sanitizer_runtime::<B>(cmd, sess, codegen_results, tmpdir, cnum);
-            }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
             _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
@@ -1457,47 +1502,6 @@
         }
     }
 
-    // We must link the sanitizer runtime using -Wl,--whole-archive but since
-    // it's packed in a .rlib, it contains stuff that are not objects that will
-    // make the linker error. So we must remove those bits from the .rlib before
-    // linking it.
-    fn link_sanitizer_runtime<'a, B: ArchiveBuilder<'a>>(
-        cmd: &mut dyn Linker,
-        sess: &'a Session,
-        codegen_results: &CodegenResults,
-        tmpdir: &Path,
-        cnum: CrateNum,
-    ) {
-        let src = &codegen_results.crate_info.used_crate_source[&cnum];
-        let cratepath = &src.rlib.as_ref().unwrap().0;
-
-        if sess.target.target.options.is_like_osx {
-            // On Apple platforms, the sanitizer is always built as a dylib, and
-            // LLVM will link to `@rpath/*.dylib`, so we need to specify an
-            // rpath to the library as well (the rpath should be absolute, see
-            // PR #41352 for details).
-            //
-            // FIXME: Remove this logic into librustc_*san once Cargo supports it
-            let rpath = cratepath.parent().unwrap();
-            let rpath = rpath.to_str().expect("non-utf8 component in path");
-            cmd.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]);
-        }
-
-        let dst = tmpdir.join(cratepath.file_name().unwrap());
-        let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
-        archive.update_symbols();
-
-        for f in archive.src_files() {
-            if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME {
-                archive.remove_file(&f);
-            }
-        }
-
-        archive.build();
-
-        cmd.link_whole_rlib(&dst);
-    }
-
     // Adds the static "rlib" versions of all crates to the command line.
     // There's a bit of magic which happens here specifically related to LTO and
     // dynamic libraries. Specifically:
@@ -1562,7 +1566,7 @@
         let name = cratepath.file_name().unwrap().to_str().unwrap();
         let name = &name[3..name.len() - 5]; // chop off lib/.rlib
 
-        sess.prof.generic_pass(&format!("altering {}.rlib", name)).run(|| {
+        sess.prof.extra_verbose_generic_activity(&format!("altering {}.rlib", name)).run(|| {
             let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
             archive.update_symbols();
 
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 11f5d30..695f171 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -20,6 +20,7 @@
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct LinkerInfo {
     exports: FxHashMap<CrateType, Vec<String>>,
 }
@@ -1103,7 +1104,11 @@
     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
     for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
         if level.is_below_threshold(export_threshold) {
-            symbols.push(symbol.symbol_name(tcx).to_string());
+            symbols.push(symbol_export::symbol_name_for_instance_in_crate(
+                tcx,
+                symbol,
+                LOCAL_CRATE,
+            ));
         }
     }
 
@@ -1124,12 +1129,7 @@
                     continue;
                 }
 
-                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
-                // We want to block export of generics from dylibs,
-                // but we must fix rust-lang/rust#65890 before we can
-                // do that robustly.
-
-                symbols.push(symbol.symbol_name(tcx).to_string());
+                symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
             }
         }
     }
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index edd0fa5..a6cd0c0 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -3,11 +3,12 @@
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
-use rustc::session::config;
+use rustc::session::config::{self, Sanitizer};
 use rustc::ty::query::Providers;
-use rustc::ty::subst::SubstsRef;
+use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::Instance;
 use rustc::ty::{SymbolName, TyCtxt};
+use rustc_codegen_utils::symbol_names;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
@@ -16,8 +17,6 @@
 use rustc_index::vec::IndexVec;
 use syntax::expand::allocator::ALLOCATOR_METHODS;
 
-pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>;
-
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
     crates_export_threshold(&tcx.sess.crate_types.borrow())
 }
@@ -95,7 +94,7 @@
                     if !generics.requires_monomorphization(tcx) &&
                         // Functions marked with #[inline] are only ever codegened
                         // with "internal" linkage and are never exported.
-                        !Instance::mono(tcx, def_id).def.requires_local(tcx)
+                        !Instance::mono(tcx, def_id).def.generates_cgu_internal_copy(tcx)
                     {
                         Some(def_id)
                     } else {
@@ -205,6 +204,16 @@
         }));
     }
 
+    if let Some(Sanitizer::Memory) = tcx.sess.opts.debugging_opts.sanitizer {
+        // Similar to profiling, preserve weak msan symbol during LTO.
+        const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"];
+
+        symbols.extend(MSAN_WEAK_SYMBOLS.iter().map(|sym| {
+            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(sym));
+            (exported_symbol, SymbolExportLevel::C)
+        }));
+    }
+
     if tcx.sess.crate_types.borrow().contains(&config::CrateType::Dylib) {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
@@ -239,19 +248,30 @@
                 continue;
             }
 
-            if let &MonoItem::Fn(Instance { def: InstanceDef::Item(def_id), substs }) = mono_item {
-                if substs.non_erasable_generics().next().is_some() {
-                    symbols
-                        .push((ExportedSymbol::Generic(def_id, substs), SymbolExportLevel::Rust));
+            match *mono_item {
+                MonoItem::Fn(Instance { def: InstanceDef::Item(def_id), substs }) => {
+                    if substs.non_erasable_generics().next().is_some() {
+                        let symbol = ExportedSymbol::Generic(def_id, substs);
+                        symbols.push((symbol, SymbolExportLevel::Rust));
+                    }
+                }
+                MonoItem::Fn(Instance { def: InstanceDef::DropGlue(_, Some(ty)), substs }) => {
+                    // A little sanity-check
+                    debug_assert_eq!(
+                        substs.non_erasable_generics().next(),
+                        Some(GenericArgKind::Type(ty))
+                    );
+                    symbols.push((ExportedSymbol::DropGlue(ty), SymbolExportLevel::Rust));
+                }
+                _ => {
+                    // Any other symbols don't qualify for sharing
                 }
             }
         }
     }
 
     // Sort so we get a stable incr. comp. hash.
-    symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
-        symbol1.compare_stable(tcx, symbol2)
-    });
+    symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
 
     Arc::new(symbols)
 }
@@ -277,24 +297,41 @@
         cnum_stable_ids
     };
 
+    let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
+
     for &cnum in cnums.iter() {
         for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
-            if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol {
-                let substs_map = instances.entry(def_id).or_default();
-
-                match substs_map.entry(substs) {
-                    Occupied(mut e) => {
-                        // If there are multiple monomorphizations available,
-                        // we select one deterministically.
-                        let other_cnum = *e.get();
-                        if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
-                            e.insert(cnum);
-                        }
+            let (def_id, substs) = match *exported_symbol {
+                ExportedSymbol::Generic(def_id, substs) => (def_id, substs),
+                ExportedSymbol::DropGlue(ty) => {
+                    if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id {
+                        (drop_in_place_fn_def_id, tcx.intern_substs(&[ty.into()]))
+                    } else {
+                        // `drop_in_place` in place does not exist, don't try
+                        // to use it.
+                        continue;
                     }
-                    Vacant(e) => {
+                }
+                ExportedSymbol::NonGeneric(..) | ExportedSymbol::NoDefId(..) => {
+                    // These are no monomorphizations
+                    continue;
+                }
+            };
+
+            let substs_map = instances.entry(def_id).or_default();
+
+            match substs_map.entry(substs) {
+                Occupied(mut e) => {
+                    // If there are multiple monomorphizations available,
+                    // we select one deterministically.
+                    let other_cnum = *e.get();
+                    if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
                         e.insert(cnum);
                     }
                 }
+                Vacant(e) => {
+                    e.insert(cnum);
+                }
             }
         }
     }
@@ -310,6 +347,17 @@
     tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
 }
 
+fn upstream_drop_glue_for_provider<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    substs: SubstsRef<'tcx>,
+) -> Option<CrateNum> {
+    if let Some(def_id) = tcx.lang_items().drop_in_place_fn() {
+        tcx.upstream_monomorphizations_for(def_id).and_then(|monos| monos.get(&substs).cloned())
+    } else {
+        None
+    }
+}
+
 fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
         !tcx.reachable_set(LOCAL_CRATE).contains(&hir_id)
@@ -324,6 +372,7 @@
     providers.exported_symbols = exported_symbols_provider_local;
     providers.upstream_monomorphizations = upstream_monomorphizations_provider;
     providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
+    providers.upstream_drop_glue_for = upstream_drop_glue_for_provider;
 }
 
 pub fn provide_extern(providers: &mut Providers<'_>) {
@@ -345,7 +394,7 @@
     if is_extern && !std_internal {
         let target = &tcx.sess.target.target.llvm_target;
         // WebAssembly cannot export data symbols, so reduce their export level
-        if target.contains("wasm32") || target.contains("emscripten") {
+        if target.contains("emscripten") {
             if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
                 tcx.hir().get_if_local(sym_def_id)
             {
@@ -358,3 +407,37 @@
         SymbolExportLevel::Rust
     }
 }
+
+/// This is the symbol name of the given instance instantiated in a specific crate.
+pub fn symbol_name_for_instance_in_crate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    symbol: ExportedSymbol<'tcx>,
+    instantiating_crate: CrateNum,
+) -> String {
+    // If this is something instantiated in the local crate then we might
+    // already have cached the name as a query result.
+    if instantiating_crate == LOCAL_CRATE {
+        return symbol.symbol_name_for_local_instance(tcx).to_string();
+    }
+
+    // This is something instantiated in an upstream crate, so we have to use
+    // the slower (because uncached) version of computing the symbol name.
+    match symbol {
+        ExportedSymbol::NonGeneric(def_id) => symbol_names::symbol_name_for_instance_in_crate(
+            tcx,
+            Instance::mono(tcx, def_id),
+            instantiating_crate,
+        ),
+        ExportedSymbol::Generic(def_id, substs) => symbol_names::symbol_name_for_instance_in_crate(
+            tcx,
+            Instance::new(def_id, substs),
+            instantiating_crate,
+        ),
+        ExportedSymbol::DropGlue(ty) => symbol_names::symbol_name_for_instance_in_crate(
+            tcx,
+            Instance::resolve_drop_in_place(tcx, ty),
+            instantiating_crate,
+        ),
+        ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
+    }
+}
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 075374f..841827d 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -2,7 +2,8 @@
 use super::link::{self, get_linker, remove};
 use super::linker::LinkerInfo;
 use super::lto::{self, SerializedModule};
-use super::symbol_export::ExportedSymbols;
+use super::symbol_export::symbol_name_for_instance_in_crate;
+
 use crate::{
     CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
     RLIB_BYTECODE_EXTENSION,
@@ -12,6 +13,7 @@
 use jobserver::{Acquired, Client};
 use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId};
 use rustc::middle::cstore::EncodedMetadata;
+use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::session::config::{
     self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath,
 };
@@ -205,6 +207,8 @@
     }
 }
 
+pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>;
+
 /// Additional resources used by optimize_and_codegen (not module specific)
 #[derive(Clone)]
 pub struct CodegenContext<B: WriteBackendMethods> {
@@ -479,6 +483,8 @@
         return work_products;
     }
 
+    let _timer = sess.timer("incr_comp_copy_cgu_workproducts");
+
     for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
         let mut files = vec![];
 
@@ -900,7 +906,7 @@
         worker_id: usize,
     },
     Done {
-        result: Result<CompiledModule, ()>,
+        result: Result<CompiledModule, Option<WorkerFatalError>>,
         worker_id: usize,
     },
     CodegenDone {
@@ -954,7 +960,7 @@
             let symbols = tcx
                 .exported_symbols(cnum)
                 .iter()
-                .map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl))
+                .map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl))
                 .collect();
             Arc::new(symbols)
         };
@@ -1472,9 +1478,12 @@
                     main_thread_worker_state = MainThreadWorkerState::Idle;
                 }
                 // If the thread failed that means it panicked, so we abort immediately.
-                Message::Done { result: Err(()), worker_id: _ } => {
+                Message::Done { result: Err(None), worker_id: _ } => {
                     bug!("worker thread panicked");
                 }
+                Message::Done { result: Err(Some(WorkerFatalError)), worker_id: _ } => {
+                    return Err(());
+                }
                 Message::CodegenItem => bug!("the coordinator should not receive codegen requests"),
             }
         }
@@ -1511,36 +1520,43 @@
         llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
     ) {
         if config.time_module && llvm_start_time.is_none() {
-            *llvm_start_time = Some(prof.generic_pass("LLVM passes"));
+            *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes"));
         }
     }
 }
 
 pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
 
+/// `FatalError` is explicitly not `Send`.
+#[must_use]
+pub struct WorkerFatalError;
+
 fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
     thread::spawn(move || {
         // Set up a destructor which will fire off a message that we're done as
         // we exit.
         struct Bomb<B: ExtraBackendMethods> {
             coordinator_send: Sender<Box<dyn Any + Send>>,
-            result: Option<WorkItemResult<B>>,
+            result: Option<Result<WorkItemResult<B>, FatalError>>,
             worker_id: usize,
         }
         impl<B: ExtraBackendMethods> Drop for Bomb<B> {
             fn drop(&mut self) {
                 let worker_id = self.worker_id;
                 let msg = match self.result.take() {
-                    Some(WorkItemResult::Compiled(m)) => {
+                    Some(Ok(WorkItemResult::Compiled(m))) => {
                         Message::Done::<B> { result: Ok(m), worker_id }
                     }
-                    Some(WorkItemResult::NeedsFatLTO(m)) => {
+                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
                         Message::NeedsFatLTO::<B> { result: m, worker_id }
                     }
-                    Some(WorkItemResult::NeedsThinLTO(name, thin_buffer)) => {
+                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
                         Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
                     }
-                    None => Message::Done::<B> { result: Err(()), worker_id },
+                    Some(Err(FatalError)) => {
+                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                    }
+                    None => Message::Done::<B> { result: Err(None), worker_id },
                 };
                 drop(self.coordinator_send.send(Box::new(msg)));
             }
@@ -1560,7 +1576,7 @@
         // surface that there was an error in this worker.
         bomb.result = {
             let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id());
-            execute_work_item(&cgcx, work).ok()
+            Some(execute_work_item(&cgcx, work))
         };
     });
 }
@@ -1679,7 +1695,6 @@
                         d.code(code);
                     }
                     handler.emit_diagnostic(&d);
-                    handler.abort_if_errors_and_should_abort();
                 }
                 Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => {
                     sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg)
@@ -1715,8 +1730,11 @@
 
 impl<B: ExtraBackendMethods> OngoingCodegen<B> {
     pub fn join(self, sess: &Session) -> (CodegenResults, FxHashMap<WorkProductId, WorkProduct>) {
+        let _timer = sess.timer("finish_ongoing_codegen");
+
         self.shared_emitter_main.check(sess, true);
-        let compiled_modules = match self.future.join() {
+        let future = self.future;
+        let compiled_modules = sess.time("join_worker_thread", || match future.join() {
             Ok(Ok(compiled_modules)) => compiled_modules,
             Ok(Err(())) => {
                 sess.abort_if_errors();
@@ -1725,7 +1743,7 @@
             Err(_) => {
                 bug!("panic during codegen/LLVM phase");
             }
-        };
+        });
 
         sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic());
 
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index ededb36..efd5600 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -14,8 +14,8 @@
 //!   int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
 
 use crate::back::write::{
-    start_async_codegen, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
-    OngoingCodegen,
+    start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm,
+    submit_pre_lto_module_to_llvm, OngoingCodegen,
 };
 use crate::common::{IntPredicate, RealPredicate, TypeKind};
 use crate::meth;
@@ -40,6 +40,7 @@
 use rustc_codegen_utils::{check_for_rustc_errors_attr, symbol_names_test};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::profiling::print_time_passes_entry;
+use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::Idx;
@@ -85,7 +86,7 @@
         }
         op => bug!(
             "comparison_op_to_icmp_predicate: expected comparison operator, \
-                  found {:?}",
+             found {:?}",
             op
         ),
     }
@@ -102,7 +103,7 @@
         op => {
             bug!(
                 "comparison_op_to_fcmp_predicate: expected comparison operator, \
-                  found {:?}",
+                 found {:?}",
                 op
             );
         }
@@ -519,7 +520,7 @@
 
         ongoing_codegen.codegen_finished(tcx);
 
-        assert_and_save_dep_graph(tcx);
+        finalize_tcx(tcx);
 
         ongoing_codegen.check_for_errors(tcx.sess);
 
@@ -566,7 +567,7 @@
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
         let mut modules = backend.new_metadata(tcx, &llmod_id);
         tcx.sess
-            .time("write allocator module", || backend.codegen_allocator(tcx, &mut modules, kind));
+            .time("write_allocator_module", || backend.codegen_allocator(tcx, &mut modules, kind));
 
         Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator })
     } else {
@@ -582,7 +583,7 @@
         let metadata_cgu_name =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
         let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name);
-        tcx.sess.time("write compressed metadata", || {
+        tcx.sess.time("write_compressed_metadata", || {
             backend.write_compressed_metadata(
                 tcx,
                 &ongoing_codegen.metadata,
@@ -606,20 +607,83 @@
         codegen_units
     };
 
-    let mut total_codegen_time = Duration::new(0, 0);
+    let total_codegen_time = Lock::new(Duration::new(0, 0));
 
-    for cgu in codegen_units.into_iter() {
+    // The non-parallel compiler can only translate codegen units to LLVM IR
+    // on a single thread, leading to a staircase effect where the N LLVM
+    // threads have to wait on the single codegen threads to generate work
+    // for them. The parallel compiler does not have this restriction, so
+    // we can pre-load the LLVM queue in parallel before handing off
+    // coordination to the OnGoingCodegen scheduler.
+    //
+    // This likely is a temporary measure. Once we don't have to support the
+    // non-parallel compiler anymore, we can compile CGUs end-to-end in
+    // parallel and get rid of the complicated scheduling logic.
+    let pre_compile_cgus = |cgu_reuse: &[CguReuse]| {
+        if cfg!(parallel_compiler) {
+            tcx.sess.time("compile_first_CGU_batch", || {
+                // Try to find one CGU to compile per thread.
+                let cgus: Vec<_> = cgu_reuse
+                    .iter()
+                    .enumerate()
+                    .filter(|&(_, reuse)| reuse == &CguReuse::No)
+                    .take(tcx.sess.threads())
+                    .collect();
+
+                // Compile the found CGUs in parallel.
+                par_iter(cgus)
+                    .map(|(i, _)| {
+                        let start_time = Instant::now();
+                        let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
+                        let mut time = total_codegen_time.lock();
+                        *time += start_time.elapsed();
+                        (i, module)
+                    })
+                    .collect()
+            })
+        } else {
+            FxHashMap::default()
+        }
+    };
+
+    let mut cgu_reuse = Vec::new();
+    let mut pre_compiled_cgus: Option<FxHashMap<usize, _>> = None;
+
+    for (i, cgu) in codegen_units.iter().enumerate() {
         ongoing_codegen.wait_for_signal_to_codegen_item();
         ongoing_codegen.check_for_errors(tcx.sess);
 
-        let cgu_reuse = determine_cgu_reuse(tcx, &cgu);
+        // Do some setup work in the first iteration
+        if pre_compiled_cgus.is_none() {
+            // Calculate the CGU reuse
+            cgu_reuse = tcx.sess.time("find_cgu_reuse", || {
+                codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect()
+            });
+            // Pre compile some CGUs
+            pre_compiled_cgus = Some(pre_compile_cgus(&cgu_reuse));
+        }
+
+        let cgu_reuse = cgu_reuse[i];
         tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse);
 
         match cgu_reuse {
             CguReuse::No => {
-                let start_time = Instant::now();
-                backend.compile_codegen_unit(tcx, cgu.name(), &ongoing_codegen.coordinator_send);
-                total_codegen_time += start_time.elapsed();
+                let (module, cost) =
+                    if let Some(cgu) = pre_compiled_cgus.as_mut().unwrap().remove(&i) {
+                        cgu
+                    } else {
+                        let start_time = Instant::now();
+                        let module = backend.compile_codegen_unit(tcx, cgu.name());
+                        let mut time = total_codegen_time.lock();
+                        *time += start_time.elapsed();
+                        module
+                    };
+                submit_codegened_module_to_llvm(
+                    &backend,
+                    &ongoing_codegen.coordinator_send,
+                    module,
+                    cost,
+                );
                 false
             }
             CguReuse::PreLto => {
@@ -652,7 +716,11 @@
 
     // Since the main thread is sometimes blocked during codegen, we keep track
     // -Ztime-passes output manually.
-    print_time_passes_entry(tcx.sess.time_passes(), "codegen to LLVM IR", total_codegen_time);
+    print_time_passes_entry(
+        tcx.sess.time_passes(),
+        "codegen_to_LLVM_IR",
+        total_codegen_time.into_inner(),
+    );
 
     ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
 
@@ -660,7 +728,8 @@
 
     ongoing_codegen.check_for_errors(tcx.sess);
 
-    assert_and_save_dep_graph(tcx);
+    finalize_tcx(tcx);
+
     ongoing_codegen.into_inner()
 }
 
@@ -711,10 +780,16 @@
     }
 }
 
-fn assert_and_save_dep_graph(tcx: TyCtxt<'_>) {
-    tcx.sess.time("assert dep graph", || ::rustc_incremental::assert_dep_graph(tcx));
+fn finalize_tcx(tcx: TyCtxt<'_>) {
+    tcx.sess.time("assert_dep_graph", || ::rustc_incremental::assert_dep_graph(tcx));
+    tcx.sess.time("serialize_dep_graph", || ::rustc_incremental::save_dep_graph(tcx));
 
-    tcx.sess.time("serialize dep graph", || ::rustc_incremental::save_dep_graph(tcx));
+    // We assume that no queries are run past here. If there are new queries
+    // after this point, they'll show up as "<unknown>" in self-profiling data.
+    {
+        let _prof_timer = tcx.prof.generic_activity("self_profile_alloc_query_strings");
+        tcx.alloc_self_profile_query_strings();
+    }
 }
 
 impl CrateInfo {
@@ -723,7 +798,6 @@
             panic_runtime: None,
             compiler_builtins: None,
             profiler_runtime: None,
-            sanitizer_runtime: None,
             is_no_builtins: Default::default(),
             native_libraries: Default::default(),
             used_libraries: tcx.native_libraries(LOCAL_CRATE),
@@ -759,9 +833,6 @@
             if tcx.is_profiler_runtime(cnum) {
                 info.profiler_runtime = Some(cnum);
             }
-            if tcx.is_sanitizer_runtime(cnum) {
-                info.sanitizer_runtime = Some(cnum);
-            }
             if tcx.is_no_builtins(cnum) {
                 info.is_no_builtins.insert(cnum);
             }
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index 299a6d9..28b61e0 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -2,6 +2,7 @@
 
 use rustc::session::Session;
 use rustc::ty::{Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_span::Span;
 
 use crate::base;
@@ -12,8 +13,6 @@
 use crate::traits::BuilderMethods;
 use rustc_hir as hir;
 
-use rustc_error_codes::*;
-
 pub enum IntPredicate {
     IntEQ,
     IntNE,
@@ -196,5 +195,5 @@
 }
 
 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
-    span_err!(a, b, E0511, "{}", c);
+    struct_span_err!(a, b, E0511, "{}", c).emit();
 }
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index b476fd9..b69def5 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(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(stmt_expr_attributes)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
@@ -21,8 +21,6 @@
 extern crate log;
 #[macro_use]
 extern crate rustc;
-#[macro_use]
-extern crate syntax;
 
 use rustc::dep_graph::WorkProduct;
 use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary};
@@ -89,7 +87,7 @@
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct CompiledModule {
     pub name: String,
     pub kind: ModuleKind,
@@ -103,7 +101,7 @@
     pub source: WorkProduct,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ModuleKind {
     Regular,
     Metadata,
@@ -119,12 +117,18 @@
 }
 
 /// Misc info we load from metadata to persist beyond the tcx.
-#[derive(Debug)]
+///
+/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
+/// is self-contained. `CrateNum` can be viewed as a unique identifier within a `CrateInfo`, where
+/// `used_crate_source` contains all `CrateSource` of the dependents, and maintains a mapping from
+/// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
+/// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
+/// and the corresponding properties without referencing information outside of a `CrateInfo`.
+#[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct CrateInfo {
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
-    pub sanitizer_runtime: Option<CrateNum>,
     pub is_no_builtins: FxHashSet<CrateNum>,
     pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
     pub crate_name: FxHashMap<CrateNum, String>,
@@ -138,6 +142,7 @@
     pub dependency_formats: Lrc<Dependencies>,
 }
 
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct CodegenResults {
     pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 0ceb44d..c3affd2 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -14,7 +14,6 @@
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_span::DUMMY_SP;
 
 pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
@@ -129,17 +128,13 @@
             };
             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.local, 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(), elem).ty;
                 let elem_ty = self.fx.monomorphize(&elem_ty);
-                let span = if let mir::PlaceBase::Local(index) = place_ref.base {
-                    self.fx.mir.local_decls[*index].source_info.span
-                } else {
-                    DUMMY_SP
-                };
+                let span = self.fx.mir.local_decls[*place_ref.local].source_info.span;
                 if cx.spanned_layout_of(elem_ty, span).is_zst() {
                     return;
                 }
@@ -179,9 +174,7 @@
                     // We use `NonUseContext::VarDebugInfo` for the base,
                     // which might not force the base local to memory,
                     // so we have to do it manually.
-                    if let mir::PlaceBase::Local(local) = place_ref.base {
-                        self.visit_local(&local, context, location);
-                    }
+                    self.visit_local(place_ref.local, context, location);
                 }
             }
 
@@ -192,7 +185,7 @@
             }
 
             self.process_place(
-                &mir::PlaceRef { base: place_ref.base, projection: proj_base },
+                &mir::PlaceRef { local: place_ref.local, projection: proj_base },
                 base_context,
                 location,
             );
@@ -219,8 +212,8 @@
                 };
             }
 
-            self.visit_place_base(place_ref.base, context, location);
-            self.visit_projection(place_ref.base, place_ref.projection, context, location);
+            self.visit_place_base(place_ref.local, context, location);
+            self.visit_projection(place_ref.local, place_ref.projection, context, location);
         }
     }
 }
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index a1d4c0c..9169010 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -10,8 +10,8 @@
 use crate::MemFlags;
 
 use rustc::middle::lang_items;
+use rustc::mir;
 use rustc::mir::interpret::PanicInfo;
-use rustc::mir::{self, PlaceBase, Static, StaticKind};
 use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_index::vec::Idx;
@@ -609,53 +609,17 @@
                     // checked by const-qualification, which also
                     // promotes any complex rvalues to constants.
                     if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
-                        match arg {
-                            // The shuffle array argument is usually not an explicit constant,
-                            // but specified directly in the code. This means it gets promoted
-                            // and we can then extract the value by evaluating the promoted.
-                            mir::Operand::Copy(place) | mir::Operand::Move(place) => {
-                                if let mir::PlaceRef {
-                                    base:
-                                        &PlaceBase::Static(box Static {
-                                            kind: StaticKind::Promoted(promoted, substs),
-                                            ty,
-                                            def_id,
-                                        }),
-                                    projection: &[],
-                                } = place.as_ref()
-                                {
-                                    let c = bx.tcx().const_eval_promoted(
-                                        Instance::new(def_id, self.monomorphize(&substs)),
-                                        promoted,
-                                    );
-                                    let (llval, ty) = self.simd_shuffle_indices(
-                                        &bx,
-                                        terminator.source_info.span,
-                                        ty,
-                                        c,
-                                    );
-                                    return OperandRef {
-                                        val: Immediate(llval),
-                                        layout: bx.layout_of(ty),
-                                    };
-                                } else {
-                                    span_bug!(span, "shuffle indices must be constant");
-                                }
-                            }
-
-                            mir::Operand::Constant(constant) => {
-                                let c = self.eval_mir_constant(constant);
-                                let (llval, ty) = self.simd_shuffle_indices(
-                                    &bx,
-                                    constant.span,
-                                    constant.literal.ty,
-                                    c,
-                                );
-                                return OperandRef {
-                                    val: Immediate(llval),
-                                    layout: bx.layout_of(ty),
-                                };
-                            }
+                        if let mir::Operand::Constant(constant) = arg {
+                            let c = self.eval_mir_constant(constant);
+                            let (llval, ty) = self.simd_shuffle_indices(
+                                &bx,
+                                constant.span,
+                                constant.literal.ty,
+                                c,
+                            );
+                            return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty) };
+                        } else {
+                            span_bug!(span, "shuffle indices must be constant");
                         }
                     }
 
@@ -1147,7 +1111,7 @@
         } else {
             self.codegen_place(
                 bx,
-                &mir::PlaceRef { base: &dest.base, projection: &dest.projection },
+                &mir::PlaceRef { local: &dest.local, projection: &dest.projection },
             )
         };
         if fn_ret.is_indirect() {
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index f508ed9..3ce916d 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -20,7 +20,7 @@
             // use `get_static` to get at their id.
             // FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics
             // always produce `&STATIC`. This may also simplify how const eval works with statics.
-            ty::ConstKind::Unevaluated(def_id, substs) if self.cx.tcx().is_static(def_id) => {
+            ty::ConstKind::Unevaluated(def_id, substs, None) if self.cx.tcx().is_static(def_id) => {
                 assert!(substs.is_empty(), "we don't support generic statics yet");
                 let static_ = bx.get_static(def_id);
                 // we treat operands referring to statics as if they were `&STATIC` instead
@@ -40,16 +40,18 @@
         constant: &mir::Constant<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
         match constant.literal.val {
-            ty::ConstKind::Unevaluated(def_id, substs) => {
+            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 let substs = self.monomorphize(&substs);
                 self.cx
                     .tcx()
-                    .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, None)
+                    .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
                     .map_err(|err| {
-                        self.cx
-                            .tcx()
-                            .sess
-                            .span_err(constant.span, "erroneous constant encountered");
+                        if promoted.is_none() {
+                            self.cx
+                                .tcx()
+                                .sess
+                                .span_err(constant.span, "erroneous constant encountered");
+                        }
                         err
                     })
             }
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index 6c17a01..e0aec5d 100644
--- a/src/librustc_codegen_ssa/mir/debuginfo.rs
+++ b/src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -258,9 +258,7 @@
     if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() {
         let mut per_local = IndexVec::from_elem(vec![], &body.local_decls);
         for var in &body.var_debug_info {
-            if let mir::PlaceBase::Local(local) = var.place.base {
-                per_local[local].push(var);
-            }
+            per_local[var.place.local].push(var);
         }
         Some(per_local)
     } else {
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index d530696..a155a6e 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -373,44 +373,40 @@
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
-        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,
+        match self.locals[*place_ref.local] {
+            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
+            }
         }
     }
 
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 7399db1..5e03a35 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -9,7 +9,7 @@
 use rustc::mir;
 use rustc::mir::tcx::PlaceTy;
 use rustc::ty::layout::{self, Align, HasTyCtxt, LayoutOf, TyLayout, VariantIdx};
-use rustc::ty::{self, Instance, Ty};
+use rustc::ty::{self, Ty};
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceRef<'tcx, V> {
@@ -37,15 +37,6 @@
         PlaceRef { llval, llextra: None, layout, align }
     }
 
-    fn new_thin_place<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        bx: &mut Bx,
-        llval: V,
-        layout: TyLayout<'tcx>,
-    ) -> PlaceRef<'tcx, V> {
-        assert!(!bx.cx().type_has_metadata(layout.ty));
-        PlaceRef { llval, llextra: None, layout, align: layout.align.abi }
-    }
-
     // FIXME(eddyb) pass something else for the name so no work is done
     // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
     pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
@@ -424,76 +415,26 @@
         let tcx = self.cx.tcx();
 
         let result = match place_ref {
-            mir::PlaceRef { base: mir::PlaceBase::Local(index), projection: [] } => {
-                match self.locals[*index] {
-                    LocalRef::Place(place) => {
-                        return place;
-                    }
-                    LocalRef::UnsizedPlace(place) => {
-                        return bx.load_operand(place).deref(cx);
-                    }
-                    LocalRef::Operand(..) => {
-                        bug!("using operand local {:?} as place", place_ref);
-                    }
+            mir::PlaceRef { local, projection: [] } => match self.locals[**local] {
+                LocalRef::Place(place) => {
+                    return place;
                 }
-            }
-            mir::PlaceRef {
-                base:
-                    mir::PlaceBase::Static(box mir::Static {
-                        ty,
-                        kind: mir::StaticKind::Promoted(promoted, substs),
-                        def_id,
-                    }),
-                projection: [],
-            } => {
-                let instance = Instance::new(*def_id, self.monomorphize(substs));
-                let layout = cx.layout_of(self.monomorphize(&ty));
-                match bx.tcx().const_eval_promoted(instance, *promoted) {
-                    Ok(val) => match val.val {
-                        ty::ConstKind::Value(mir::interpret::ConstValue::ByRef {
-                            alloc,
-                            offset,
-                        }) => bx.cx().from_const_alloc(layout, alloc, offset),
-                        _ => bug!("promoteds should have an allocation: {:?}", val),
-                    },
-                    Err(_) => {
-                        // This is unreachable as long as runtime
-                        // and compile-time agree perfectly.
-                        // With floats that won't always be true,
-                        // so we generate a (safe) abort.
-                        bx.abort();
-                        // We still have to return a place but it doesn't matter,
-                        // this code is unreachable.
-                        let llval =
-                            bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout)));
-                        PlaceRef::new_sized(llval, layout)
-                    }
+                LocalRef::UnsizedPlace(place) => {
+                    return bx.load_operand(place).deref(cx);
                 }
-            }
-            mir::PlaceRef {
-                base:
-                    mir::PlaceBase::Static(box mir::Static {
-                        ty,
-                        kind: mir::StaticKind::Static,
-                        def_id,
-                    }),
-                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)
-            }
-            mir::PlaceRef { base, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
+                LocalRef::Operand(..) => {
+                    bug!("using operand local {:?} as place", place_ref);
+                }
+            },
+            mir::PlaceRef { local, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
                 // Load the pointer from its location.
-                self.codegen_consume(bx, &mir::PlaceRef { base, projection: proj_base })
+                self.codegen_consume(bx, &mir::PlaceRef { local, projection: proj_base })
                     .deref(bx.cx())
             }
-            mir::PlaceRef { base, projection: [proj_base @ .., elem] } => {
+            mir::PlaceRef { local, projection: [proj_base @ .., elem] } => {
                 // FIXME turn this recursion into iteration
                 let cg_base =
-                    self.codegen_place(bx, &mir::PlaceRef { base, projection: proj_base });
+                    self.codegen_place(bx, &mir::PlaceRef { local, projection: proj_base });
 
                 match elem {
                     mir::ProjectionElem::Deref => bug!(),
@@ -558,7 +499,7 @@
 
     pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
-        let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, *self.mir, tcx);
+        let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
         self.monomorphize(&place_ty.ty)
     }
 }
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 48ba641..8422c62 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -1,4 +1,5 @@
 use rustc::mir;
+use rustc_errors::struct_span_err;
 
 use super::FunctionCx;
 use super::LocalRef;
@@ -6,8 +7,6 @@
 use crate::traits::BuilderMethods;
 use crate::traits::*;
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>) -> Bx {
         debug!("codegen_statement(statement={:?})", statement);
@@ -81,12 +80,13 @@
                         if let OperandValue::Immediate(_) = op.val {
                             acc.push(op.immediate());
                         } else {
-                            span_err!(
+                            struct_span_err!(
                                 bx.sess(),
                                 span.to_owned(),
                                 E0669,
                                 "invalid value for constraint in inline assembly"
-                            );
+                            )
+                            .emit();
                         }
                         acc
                     },
@@ -100,12 +100,13 @@
                         statement.source_info.span,
                     );
                     if !res {
-                        span_err!(
+                        struct_span_err!(
                             bx.sess(),
                             statement.source_info.span,
                             E0668,
                             "malformed inline assembly"
-                        );
+                        )
+                        .emit();
                     }
                 }
                 bx
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index e0d0a2f..bc3a752 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -1,5 +1,6 @@
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
+use crate::ModuleCodegen;
 
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::{config, Session};
@@ -10,7 +11,6 @@
 use rustc_span::symbol::Symbol;
 use syntax::expand::allocator::AllocatorKind;
 
-use std::sync::mpsc;
 use std::sync::Arc;
 
 pub trait BackendTypes {
@@ -34,7 +34,7 @@
 {
 }
 
-pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send {
+pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync {
     fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module;
     fn write_compressed_metadata<'tcx>(
         &self,
@@ -48,12 +48,13 @@
         mods: &mut Self::Module,
         kind: AllocatorKind,
     );
+    /// This generates the codegen unit and returns it along with
+    /// a `u64` giving an estimate of the unit's processing cost.
     fn compile_codegen_unit(
         &self,
         tcx: TyCtxt<'_>,
         cgu_name: Symbol,
-        tx_to_llvm_workers: &mpsc::Sender<Box<dyn std::any::Any + Send>>,
-    );
+    ) -> (ModuleCodegen<Self::Module>, u64);
     // If find_features is true this won't access `sess.crate_types` by assuming
     // that `is_pie_binary` is false. When we discover LLVM target features
     // `sess.crate_types` is uninitialized so we cannot access it.
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 450dcd3..6713459 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -91,8 +91,9 @@
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::session::config::SymbolManglingVersion;
 use rustc::ty::query::Providers;
+use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Instance, TyCtxt};
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::Node;
 
 use rustc_span::symbol::Symbol;
@@ -102,15 +103,51 @@
 mod legacy;
 mod v0;
 
-pub fn provide(providers: &mut Providers<'_>) {
-    *providers = Providers {
-        symbol_name: |tcx, instance| ty::SymbolName { name: symbol_name(tcx, instance) },
-
-        ..*providers
-    };
+/// This function computes the symbol name for the given `instance` and the
+/// given instantiating crate. That is, if you know that instance X is
+/// instantiated in crate Y, this is the symbol name this instance would have.
+pub fn symbol_name_for_instance_in_crate(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    instantiating_crate: CrateNum,
+) -> String {
+    compute_symbol_name(tcx, instance, || instantiating_crate)
 }
 
-fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
+pub fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers { symbol_name: symbol_name_provider, ..*providers };
+}
+
+// The `symbol_name` query provides the symbol name for calling a given
+// instance from the local crate. In particular, it will also look up the
+// correct symbol name of instances from upstream crates.
+fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName {
+    let symbol_name = compute_symbol_name(tcx, instance, || {
+        // This closure determines the instantiating crate for instances that
+        // need an instantiating-crate-suffix for their symbol name, in order
+        // to differentiate between local copies.
+        if is_generic(instance.substs) {
+            // For generics we might find re-usable upstream instances. If there
+            // is one, we rely on the symbol being instantiated locally.
+            instance.upstream_monomorphization(tcx).unwrap_or(LOCAL_CRATE)
+        } else {
+            // For non-generic things that need to avoid naming conflicts, we
+            // always instantiate a copy in the local crate.
+            LOCAL_CRATE
+        }
+    });
+
+    ty::SymbolName { name: Symbol::intern(&symbol_name) }
+}
+
+/// Computes the symbol name for the given instance. This function will call
+/// `compute_instantiating_crate` if it needs to factor the instantiating crate
+/// into the symbol name.
+fn compute_symbol_name(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    compute_instantiating_crate: impl FnOnce() -> CrateNum,
+) -> String {
     let def_id = instance.def_id();
     let substs = instance.substs;
 
@@ -121,11 +158,11 @@
     if def_id.is_local() {
         if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator));
+            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
         if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator));
+            return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
     }
 
@@ -162,29 +199,28 @@
             || !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id)
         {
             if let Some(name) = attrs.link_name {
-                return name;
+                return name.to_string();
             }
-            return tcx.item_name(def_id);
+            return tcx.item_name(def_id).to_string();
         }
     }
 
     if let Some(name) = attrs.export_name {
         // Use provided name
-        return name;
+        return name.to_string();
     }
 
     if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
         // Don't mangle
-        return tcx.item_name(def_id);
+        return tcx.item_name(def_id).to_string();
     }
 
-    let is_generic = substs.non_erasable_generics().next().is_some();
     let avoid_cross_crate_conflicts =
         // If this is an instance of a generic function, we also hash in
         // the ID of the instantiating crate. This avoids symbol conflicts
         // in case the same instances is emitted in two crates of the same
         // project.
-        is_generic ||
+        is_generic(substs) ||
 
         // If we're dealing with an instance of a function that's inlined from
         // another crate but we're marking it as globally shared to our
@@ -197,25 +233,8 @@
             _ => false,
         };
 
-    let instantiating_crate = if avoid_cross_crate_conflicts {
-        Some(if is_generic {
-            if !def_id.is_local() && tcx.sess.opts.share_generics() {
-                // If we are re-using a monomorphization from another crate,
-                // we have to compute the symbol hash accordingly.
-                let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id);
-
-                upstream_monomorphizations
-                    .and_then(|monos| monos.get(&substs).cloned())
-                    .unwrap_or(LOCAL_CRATE)
-            } else {
-                LOCAL_CRATE
-            }
-        } else {
-            LOCAL_CRATE
-        })
-    } else {
-        None
-    };
+    let instantiating_crate =
+        if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };
 
     // Pick the crate responsible for the symbol mangling version, which has to:
     // 1. be stable for each instance, whether it's being defined or imported
@@ -232,10 +251,12 @@
         tcx.symbol_mangling_version(mangling_version_crate)
     };
 
-    let mangled = match mangling_version {
+    match mangling_version {
         SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate),
         SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
-    };
+    }
+}
 
-    Symbol::intern(&mangled)
+fn is_generic(substs: SubstsRef<'_>) -> bool {
+    substs.non_erasable_generics().next().is_some()
 }
diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs
index 4f5b9ce..0dedda9 100644
--- a/src/librustc_codegen_utils/symbol_names/legacy.rs
+++ b/src/librustc_codegen_utils/symbol_names/legacy.rs
@@ -237,7 +237,7 @@
         // only print integers
         if let ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { .. })) = ct.val {
             if ct.ty.is_integral() {
-                return self.pretty_print_const(ct);
+                return self.pretty_print_const(ct, true);
             }
         }
         self.write_str("_")?;
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 7fa40b8..fb4f818 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,8 +26,11 @@
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
-measureme = "0.5"
+measureme = "0.7.1"
 
 [dependencies.parking_lot]
 version = "0.9"
 features = ["nightly"]
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["fileapi", "psapi"] }
diff --git a/src/librustc_data_structures/binary_search_util/mod.rs b/src/librustc_data_structures/binary_search_util/mod.rs
index 6d1e1ab..ede5757 100644
--- a/src/librustc_data_structures/binary_search_util/mod.rs
+++ b/src/librustc_data_structures/binary_search_util/mod.rs
@@ -14,35 +14,55 @@
         Ok(mid) => mid,
         Err(_) => return &[],
     };
+    let size = data.len();
 
-    // We get back *some* element with the given key -- so
-    // search backwards to find the *first* one.
-    //
-    // (It'd be more efficient to use a "galloping" search
-    // here, but it's not really worth it for small-ish
-    // amounts of data.)
+    // We get back *some* element with the given key -- so do
+    // a galloping search backwards to find the *first* one.
     let mut start = mid;
-    while start > 0 {
-        if key_fn(&data[start - 1]) == *key {
-            start -= 1;
-        } else {
+    let mut previous = mid;
+    let mut step = 1;
+    loop {
+        start = start.saturating_sub(step);
+        if start == 0 || key_fn(&data[start]) != *key {
             break;
         }
+        previous = start;
+        step *= 2;
+    }
+    step = previous - start;
+    while step > 1 {
+        let half = step / 2;
+        let mid = start + half;
+        if key_fn(&data[mid]) != *key {
+            start = mid;
+        }
+        step -= half;
+    }
+    // adjust by one if we have overshot
+    if start < size && key_fn(&data[start]) != *key {
+        start += 1;
     }
 
     // Now search forward to find the *last* one.
-    //
-    // (It'd be more efficient to use a "galloping" search
-    // here, but it's not really worth it for small-ish
-    // amounts of data.)
-    let mut end = mid + 1;
-    let max = data.len();
-    while end < max {
-        if key_fn(&data[end]) == *key {
-            end += 1;
-        } else {
+    let mut end = mid;
+    let mut previous = mid;
+    let mut step = 1;
+    loop {
+        end = end.saturating_add(step).min(size);
+        if end == size || key_fn(&data[end]) != *key {
             break;
         }
+        previous = end;
+        step *= 2;
+    }
+    step = end - previous;
+    while step > 1 {
+        let half = step / 2;
+        let mid = end - half;
+        if key_fn(&data[mid]) != *key {
+            end = mid;
+        }
+        step -= half;
     }
 
     &data[start..end]
diff --git a/src/librustc/util/captures.rs b/src/librustc_data_structures/captures.rs
similarity index 100%
rename from src/librustc/util/captures.rs
rename to src/librustc_data_structures/captures.rs
diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs
index e3282c5..2a0139f 100644
--- a/src/librustc_data_structures/flock.rs
+++ b/src/librustc_data_structures/flock.rs
@@ -87,39 +87,11 @@
     } else if #[cfg(windows)] {
         use std::mem;
         use std::os::windows::prelude::*;
-        use std::os::windows::raw::HANDLE;
         use std::fs::{File, OpenOptions};
-        use std::os::raw::{c_ulong, c_int};
 
-        type DWORD = c_ulong;
-        type BOOL = c_int;
-        type ULONG_PTR = usize;
-
-        type LPOVERLAPPED = *mut OVERLAPPED;
-        const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002;
-        const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001;
-
-        const FILE_SHARE_DELETE: DWORD = 0x4;
-        const FILE_SHARE_READ: DWORD = 0x1;
-        const FILE_SHARE_WRITE: DWORD = 0x2;
-
-        #[repr(C)]
-        struct OVERLAPPED {
-            Internal: ULONG_PTR,
-            InternalHigh: ULONG_PTR,
-            Offset: DWORD,
-            OffsetHigh: DWORD,
-            hEvent: HANDLE,
-        }
-
-        extern "system" {
-            fn LockFileEx(hFile: HANDLE,
-                          dwFlags: DWORD,
-                          dwReserved: DWORD,
-                          nNumberOfBytesToLockLow: DWORD,
-                          nNumberOfBytesToLockHigh: DWORD,
-                          lpOverlapped: LPOVERLAPPED) -> BOOL;
-        }
+        use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
+        use winapi::um::fileapi::LockFileEx;
+        use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
 
         #[derive(Debug)]
         pub struct Lock {
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index d1b7ee9..6db2910 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -33,9 +33,6 @@
 #[macro_use]
 extern crate cfg_if;
 
-#[cfg(windows)]
-extern crate libc;
-
 pub use rustc_serialize::hex::ToHex;
 
 #[inline(never)]
@@ -67,6 +64,7 @@
 pub mod base_n;
 pub mod binary_search_util;
 pub mod box_region;
+pub mod captures;
 pub mod const_cstr;
 pub mod flock;
 pub mod fx;
diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs
index 840a260..44cef72 100644
--- a/src/librustc_data_structures/profiling.rs
+++ b/src/librustc_data_structures/profiling.rs
@@ -1,6 +1,90 @@
+//! # Rust Compiler Self-Profiling
+//!
+//! This module implements the basic framework for the compiler's self-
+//! profiling support. It provides the `SelfProfiler` type which enables
+//! recording "events". An event is something that starts and ends at a given
+//! point in time and has an ID and a kind attached to it. This allows for
+//! tracing the compiler's activity.
+//!
+//! Internally this module uses the custom tailored [measureme][mm] crate for
+//! efficiently recording events to disk in a compact format that can be
+//! post-processed and analyzed by the suite of tools in the `measureme`
+//! project. The highest priority for the tracing framework is on incurring as
+//! little overhead as possible.
+//!
+//!
+//! ## Event Overview
+//!
+//! Events have a few properties:
+//!
+//! - The `event_kind` designates the broad category of an event (e.g. does it
+//!   correspond to the execution of a query provider or to loading something
+//!   from the incr. comp. on-disk cache, etc).
+//! - The `event_id` designates the query invocation or function call it
+//!   corresponds to, possibly including the query key or function arguments.
+//! - Each event stores the ID of the thread it was recorded on.
+//! - The timestamp stores beginning and end of the event, or the single point
+//!   in time it occurred at for "instant" events.
+//!
+//!
+//! ## Event Filtering
+//!
+//! Event generation can be filtered by event kind. Recording all possible
+//! events generates a lot of data, much of which is not needed for most kinds
+//! of analysis. So, in order to keep overhead as low as possible for a given
+//! use case, the `SelfProfiler` will only record the kinds of events that
+//! pass the filter specified as a command line argument to the compiler.
+//!
+//!
+//! ## `event_id` Assignment
+//!
+//! As far as `measureme` is concerned, `event_id`s are just strings. However,
+//! it would incur too much overhead to generate and persist each `event_id`
+//! string at the point where the event is recorded. In order to make this more
+//! efficient `measureme` has two features:
+//!
+//! - Strings can share their content, so that re-occurring parts don't have to
+//!   be copied over and over again. One allocates a string in `measureme` and
+//!   gets back a `StringId`. This `StringId` is then used to refer to that
+//!   string. `measureme` strings are actually DAGs of string components so that
+//!   arbitrary sharing of substrings can be done efficiently. This is useful
+//!   because `event_id`s contain lots of redundant text like query names or
+//!   def-path components.
+//!
+//! - `StringId`s can be "virtual" which means that the client picks a numeric
+//!   ID according to some application-specific scheme and can later make that
+//!   ID be mapped to an actual string. This is used to cheaply generate
+//!   `event_id`s while the events actually occur, causing little timing
+//!   distortion, and then later map those `StringId`s, in bulk, to actual
+//!   `event_id` strings. This way the largest part of the tracing overhead is
+//!   localized to one contiguous chunk of time.
+//!
+//! How are these `event_id`s generated in the compiler? For things that occur
+//! infrequently (e.g. "generic activities"), we just allocate the string the
+//! first time it is used and then keep the `StringId` in a hash table. This
+//! is implemented in `SelfProfiler::get_or_alloc_cached_string()`.
+//!
+//! For queries it gets more interesting: First we need a unique numeric ID for
+//! each query invocation (the `QueryInvocationId`). This ID is used as the
+//! virtual `StringId` we use as `event_id` for a given event. This ID has to
+//! be available both when the query is executed and later, together with the
+//! query key, when we allocate the actual `event_id` strings in bulk.
+//!
+//! We could make the compiler generate and keep track of such an ID for each
+//! query invocation but luckily we already have something that fits all the
+//! the requirements: the query's `DepNodeIndex`. So we use the numeric value
+//! of the `DepNodeIndex` as `event_id` when recording the event and then,
+//! just before the query context is dropped, we walk the entire query cache
+//! (which stores the `DepNodeIndex` along with the query key for each
+//! invocation) and allocate the corresponding strings together with a mapping
+//! for `DepNodeIndex as StringId`.
+//!
+//! [mm]: https://github.com/rust-lang/measureme/
+
+use crate::fx::FxHashMap;
+
 use std::error::Error;
 use std::fs;
-use std::mem::{self, Discriminant};
 use std::path::Path;
 use std::process;
 use std::sync::Arc;
@@ -8,9 +92,8 @@
 use std::time::{Duration, Instant};
 use std::u32;
 
-use crate::cold_path;
-
-use measureme::StringId;
+use measureme::{EventId, EventIdBuilder, SerializableString, StringId};
+use parking_lot::RwLock;
 
 /// MmapSerializatioSink is faster on macOS and Linux
 /// but FileSerializationSink is faster on Windows
@@ -21,11 +104,6 @@
 
 type Profiler = measureme::Profiler<SerializationSink>;
 
-pub trait QueryName: Sized + Copy {
-    fn discriminant(self) -> Discriminant<Self>;
-    fn as_str(self) -> &'static str;
-}
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
 pub enum ProfileCategory {
     Parsing,
@@ -44,15 +122,13 @@
         const QUERY_CACHE_HITS   = 1 << 2;
         const QUERY_BLOCKED      = 1 << 3;
         const INCR_CACHE_LOADS   = 1 << 4;
-        const SPARSE_PASS   = 1 << 5;
-        const GENERIC_PASS   = 1 << 6;
+
+        const QUERY_KEYS         = 1 << 5;
 
         const DEFAULT = Self::GENERIC_ACTIVITIES.bits |
                         Self::QUERY_PROVIDERS.bits |
                         Self::QUERY_BLOCKED.bits |
-                        Self::INCR_CACHE_LOADS.bits |
-                        Self::SPARSE_PASS.bits |
-                        Self::GENERIC_PASS.bits;
+                        Self::INCR_CACHE_LOADS.bits;
 
         // empty() and none() aren't const-fns unfortunately
         const NONE = 0;
@@ -60,22 +136,26 @@
     }
 }
 
+// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs
 const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("none", EventFilter::NONE),
     ("all", EventFilter::ALL),
-    ("sparse-pass", EventFilter::SPARSE_PASS),
-    ("generic-pass", EventFilter::GENERIC_PASS),
+    ("default", EventFilter::DEFAULT),
     ("generic-activity", EventFilter::GENERIC_ACTIVITIES),
     ("query-provider", EventFilter::QUERY_PROVIDERS),
     ("query-cache-hit", EventFilter::QUERY_CACHE_HITS),
     ("query-blocked", EventFilter::QUERY_BLOCKED),
     ("incr-cache-load", EventFilter::INCR_CACHE_LOADS),
+    ("query-keys", EventFilter::QUERY_KEYS),
 ];
 
 fn thread_id_to_u32(tid: ThreadId) -> u32 {
-    unsafe { mem::transmute::<ThreadId, u64>(tid) as u32 }
+    unsafe { std::mem::transmute::<ThreadId, u64>(tid) as u32 }
 }
 
+/// Something that uniquely identifies a query invocation.
+pub struct QueryInvocationId(pub u32);
+
 /// A reference to the SelfProfiler. It can be cloned and sent across thread
 /// boundaries at will.
 #[derive(Clone)]
@@ -89,110 +169,99 @@
     // actually enabled.
     event_filter_mask: EventFilter,
 
-    // Print sparse passes to stdout
-    verbose_sparse: bool,
+    // Print verbose generic activities to stdout
+    print_verbose_generic_activities: bool,
 
-    // Print generic passes to stdout
-    verbose_generic: bool,
+    // Print extra verbose generic activities to stdout
+    print_extra_verbose_generic_activities: bool,
 }
 
 impl SelfProfilerRef {
     pub fn new(
         profiler: Option<Arc<SelfProfiler>>,
-        verbose_sparse: bool,
-        verbose_generic: bool,
+        print_verbose_generic_activities: bool,
+        print_extra_verbose_generic_activities: bool,
     ) -> SelfProfilerRef {
         // If there is no SelfProfiler then the filter mask is set to NONE,
         // ensuring that nothing ever tries to actually access it.
-        let mut event_filter_mask =
+        let event_filter_mask =
             profiler.as_ref().map(|p| p.event_filter_mask).unwrap_or(EventFilter::NONE);
 
-        if verbose_sparse {
-            event_filter_mask |= EventFilter::SPARSE_PASS;
+        SelfProfilerRef {
+            profiler,
+            event_filter_mask,
+            print_verbose_generic_activities,
+            print_extra_verbose_generic_activities,
         }
-
-        if verbose_generic {
-            event_filter_mask |= EventFilter::GENERIC_PASS;
-        }
-
-        SelfProfilerRef { profiler, event_filter_mask, verbose_sparse, verbose_generic }
     }
 
-    #[inline(always)]
-    fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
-    where
-        F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
-    {
-        self.handle_event(
-            event_filter,
-            || f(self.profiler.as_ref().unwrap()),
-            || TimingGuard::none(),
-        )
-    }
-
-    // This shim makes sure that cold calls only get executed if the filter mask
+    // This shim makes sure that calls only get executed if the filter mask
     // lets them pass. It also contains some trickery to make sure that
     // code is optimized for non-profiling compilation sessions, i.e. anything
     // past the filter check is never inlined so it doesn't clutter the fast
     // path.
     #[inline(always)]
-    fn handle_event<R>(
-        &self,
-        event_filter: EventFilter,
-        cold: impl FnOnce() -> R,
-        hot: impl FnOnce() -> R,
-    ) -> R {
+    fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
+    where
+        F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
+    {
+        #[inline(never)]
+        fn cold_call<F>(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_>
+        where
+            F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
+        {
+            let profiler = profiler_ref.profiler.as_ref().unwrap();
+            f(&**profiler)
+        }
+
         if unlikely!(self.event_filter_mask.contains(event_filter)) {
-            cold_path(|| cold())
+            cold_call(self, f)
         } else {
-            hot()
+            TimingGuard::none()
         }
     }
 
-    /// Start profiling a sparse pass. Profiling continues until the
-    /// VerboseTimingGuard returned from this call is dropped.
+    /// Start profiling a verbose generic activity. Profiling continues until the
+    /// VerboseTimingGuard returned from this call is dropped. In addition to recording
+    /// a measureme event, "verbose" generic activities also print a timing entry to
+    /// stdout if the compiler is invoked with -Ztime or -Ztime-passes.
     #[inline(always)]
-    pub fn sparse_pass<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> {
-        self.handle_event(
-            EventFilter::SPARSE_PASS,
-            || {
-                VerboseTimingGuard::start(
-                    self.profiler
-                        .as_ref()
-                        .map(|profiler| (&**profiler, profiler.sparse_pass_event_kind)),
-                    event_id,
-                    self.verbose_sparse,
-                )
-            },
-            || VerboseTimingGuard::none(),
+    pub fn verbose_generic_activity<'a>(
+        &'a self,
+        event_id: &'static str,
+    ) -> VerboseTimingGuard<'a> {
+        VerboseTimingGuard::start(
+            event_id,
+            self.print_verbose_generic_activities,
+            self.generic_activity(event_id),
         )
     }
 
-    /// Start profiling a generic pass. Profiling continues until the
-    /// VerboseTimingGuard returned from this call is dropped.
+    /// Start profiling a extra verbose generic activity. Profiling continues until the
+    /// VerboseTimingGuard returned from this call is dropped. In addition to recording
+    /// a measureme event, "extra verbose" generic activities also print a timing entry to
+    /// stdout if the compiler is invoked with -Ztime-passes.
     #[inline(always)]
-    pub fn generic_pass<'a>(&'a self, event_id: &'a str) -> VerboseTimingGuard<'a> {
-        self.handle_event(
-            EventFilter::GENERIC_PASS,
-            || {
-                VerboseTimingGuard::start(
-                    self.profiler
-                        .as_ref()
-                        .map(|profiler| (&**profiler, profiler.generic_pass_event_kind)),
-                    event_id,
-                    self.verbose_generic,
-                )
-            },
-            || VerboseTimingGuard::none(),
+    pub fn extra_verbose_generic_activity<'a>(
+        &'a self,
+        event_id: &'a str,
+    ) -> VerboseTimingGuard<'a> {
+        // FIXME: This does not yet emit a measureme event
+        // because callers encode arguments into `event_id`.
+        VerboseTimingGuard::start(
+            event_id,
+            self.print_extra_verbose_generic_activities,
+            TimingGuard::none(),
         )
     }
 
     /// Start profiling a generic activity. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn generic_activity(&self, event_id: &str) -> TimingGuard<'_> {
+    pub fn generic_activity(&self, event_id: &'static str) -> TimingGuard<'_> {
         self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
-            let event_id = profiler.profiler.alloc_string(event_id);
+            let event_id = profiler.get_or_alloc_cached_string(event_id);
+            let event_id = EventId::from_label(event_id);
             TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
         })
     }
@@ -200,19 +269,18 @@
     /// Start profiling a query provider. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn query_provider(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn query_provider(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::QUERY_PROVIDERS, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.query_event_kind, event_id)
+            TimingGuard::start(profiler, profiler.query_event_kind, EventId::INVALID)
         })
     }
 
     /// Record a query in-memory cache hit.
     #[inline(always)]
-    pub fn query_cache_hit(&self, query_name: impl QueryName) {
+    pub fn query_cache_hit(&self, query_invocation_id: QueryInvocationId) {
         self.instant_query_event(
             |profiler| profiler.query_cache_hit_event_kind,
-            query_name,
+            query_invocation_id,
             EventFilter::QUERY_CACHE_HITS,
         );
     }
@@ -221,10 +289,9 @@
     /// Profiling continues until the TimingGuard returned from this call is
     /// dropped.
     #[inline(always)]
-    pub fn query_blocked(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn query_blocked(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::QUERY_BLOCKED, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id)
+            TimingGuard::start(profiler, profiler.query_blocked_event_kind, EventId::INVALID)
         })
     }
 
@@ -232,10 +299,13 @@
     /// incremental compilation on-disk cache. Profiling continues until the
     /// TimingGuard returned from this call is dropped.
     #[inline(always)]
-    pub fn incr_cache_loading(&self, query_name: impl QueryName) -> TimingGuard<'_> {
+    pub fn incr_cache_loading(&self) -> TimingGuard<'_> {
         self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            TimingGuard::start(profiler, profiler.incremental_load_result_event_kind, event_id)
+            TimingGuard::start(
+                profiler,
+                profiler.incremental_load_result_event_kind,
+                EventId::INVALID,
+            )
         })
     }
 
@@ -243,32 +313,42 @@
     fn instant_query_event(
         &self,
         event_kind: fn(&SelfProfiler) -> StringId,
-        query_name: impl QueryName,
+        query_invocation_id: QueryInvocationId,
         event_filter: EventFilter,
     ) {
         drop(self.exec(event_filter, |profiler| {
-            let event_id = SelfProfiler::get_query_name_string_id(query_name);
+            let event_id = StringId::new_virtual(query_invocation_id.0);
             let thread_id = thread_id_to_u32(std::thread::current().id());
 
-            profiler.profiler.record_instant_event(event_kind(profiler), event_id, thread_id);
+            profiler.profiler.record_instant_event(
+                event_kind(profiler),
+                EventId::from_virtual(event_id),
+                thread_id,
+            );
 
             TimingGuard::none()
         }));
     }
 
-    pub fn register_queries(&self, f: impl FnOnce(&SelfProfiler)) {
+    pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) {
         if let Some(profiler) = &self.profiler {
             f(&profiler)
         }
     }
+
+    #[inline]
+    pub fn enabled(&self) -> bool {
+        self.profiler.is_some()
+    }
 }
 
 pub struct SelfProfiler {
     profiler: Profiler,
     event_filter_mask: EventFilter,
+
+    string_cache: RwLock<FxHashMap<&'static str, StringId>>,
+
     query_event_kind: StringId,
-    sparse_pass_event_kind: StringId,
-    generic_pass_event_kind: StringId,
     generic_activity_event_kind: StringId,
     incremental_load_result_event_kind: StringId,
     query_blocked_event_kind: StringId,
@@ -289,8 +369,6 @@
         let profiler = Profiler::new(&path)?;
 
         let query_event_kind = profiler.alloc_string("Query");
-        let sparse_pass_event_kind = profiler.alloc_string("SparsePass");
-        let generic_pass_event_kind = profiler.alloc_string("GenericPass");
         let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
         let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
         let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
@@ -332,9 +410,8 @@
         Ok(SelfProfiler {
             profiler,
             event_filter_mask,
+            string_cache: RwLock::new(FxHashMap::default()),
             query_event_kind,
-            sparse_pass_event_kind,
-            generic_pass_event_kind,
             generic_activity_event_kind,
             incremental_load_result_event_kind,
             query_blocked_event_kind,
@@ -342,16 +419,51 @@
         })
     }
 
-    fn get_query_name_string_id(query_name: impl QueryName) -> StringId {
-        let discriminant =
-            unsafe { mem::transmute::<Discriminant<_>, u64>(query_name.discriminant()) };
-
-        StringId::reserved(discriminant as u32)
+    /// Allocates a new string in the profiling data. Does not do any caching
+    /// or deduplication.
+    pub fn alloc_string<STR: SerializableString + ?Sized>(&self, s: &STR) -> StringId {
+        self.profiler.alloc_string(s)
     }
 
-    pub fn register_query_name(&self, query_name: impl QueryName) {
-        let id = SelfProfiler::get_query_name_string_id(query_name);
-        self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
+    /// Gets a `StringId` for the given string. This method makes sure that
+    /// any strings going through it will only be allocated once in the
+    /// profiling data.
+    pub fn get_or_alloc_cached_string(&self, s: &'static str) -> StringId {
+        // Only acquire a read-lock first since we assume that the string is
+        // already present in the common case.
+        {
+            let string_cache = self.string_cache.read();
+
+            if let Some(&id) = string_cache.get(s) {
+                return id;
+            }
+        }
+
+        let mut string_cache = self.string_cache.write();
+        // Check if the string has already been added in the small time window
+        // between dropping the read lock and acquiring the write lock.
+        *string_cache.entry(s).or_insert_with(|| self.profiler.alloc_string(s))
+    }
+
+    pub fn map_query_invocation_id_to_string(&self, from: QueryInvocationId, to: StringId) {
+        let from = StringId::new_virtual(from.0);
+        self.profiler.map_virtual_to_concrete_string(from, to);
+    }
+
+    pub fn bulk_map_query_invocation_id_to_single_string<I>(&self, from: I, to: StringId)
+    where
+        I: Iterator<Item = QueryInvocationId> + ExactSizeIterator,
+    {
+        let from = from.map(|qid| StringId::new_virtual(qid.0));
+        self.profiler.bulk_map_virtual_to_single_concrete_string(from, to);
+    }
+
+    pub fn query_key_recording_enabled(&self) -> bool {
+        self.event_filter_mask.contains(EventFilter::QUERY_KEYS)
+    }
+
+    pub fn event_id_builder(&self) -> EventIdBuilder<'_, SerializationSink> {
+        EventIdBuilder::new(&self.profiler)
     }
 }
 
@@ -363,7 +475,7 @@
     pub fn start(
         profiler: &'a SelfProfiler,
         event_kind: StringId,
-        event_id: StringId,
+        event_id: EventId,
     ) -> TimingGuard<'a> {
         let thread_id = thread_id_to_u32(std::thread::current().id());
         let raw_profiler = &profiler.profiler;
@@ -373,9 +485,24 @@
     }
 
     #[inline]
+    pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) {
+        if let Some(guard) = self.0 {
+            let event_id = StringId::new_virtual(query_invocation_id.0);
+            let event_id = EventId::from_virtual(event_id);
+            guard.finish_with_override_event_id(event_id);
+        }
+    }
+
+    #[inline]
     pub fn none() -> TimingGuard<'a> {
         TimingGuard(None)
     }
+
+    #[inline(always)]
+    pub fn run<R>(self, f: impl FnOnce() -> R) -> R {
+        let _timer = self;
+        f()
+    }
 }
 
 #[must_use]
@@ -386,19 +513,11 @@
 }
 
 impl<'a> VerboseTimingGuard<'a> {
-    pub fn start(
-        profiler: Option<(&'a SelfProfiler, StringId)>,
-        event_id: &'a str,
-        verbose: bool,
-    ) -> Self {
-        let _guard = profiler.map_or(TimingGuard::none(), |(profiler, event_kind)| {
-            let event = profiler.profiler.alloc_string(event_id);
-            TimingGuard::start(profiler, event_kind, event)
-        });
+    pub fn start(event_id: &'a str, verbose: bool, _guard: TimingGuard<'a>) -> Self {
         VerboseTimingGuard {
             event_id,
             _guard,
-            start: if verbose { Some(Instant::now()) } else { None },
+            start: if unlikely!(verbose) { Some(Instant::now()) } else { None },
         }
     }
 
@@ -407,10 +526,6 @@
         let _timer = self;
         f()
     }
-
-    fn none() -> Self {
-        VerboseTimingGuard { event_id: "", start: None, _guard: TimingGuard::none() }
-    }
 }
 
 impl Drop for VerboseTimingGuard<'_> {
@@ -456,39 +571,19 @@
 
 #[cfg(windows)]
 fn get_resident() -> Option<usize> {
-    type BOOL = i32;
-    type DWORD = u32;
-    type HANDLE = *mut u8;
-    use libc::size_t;
-    #[repr(C)]
-    #[allow(non_snake_case)]
-    struct PROCESS_MEMORY_COUNTERS {
-        cb: DWORD,
-        PageFaultCount: DWORD,
-        PeakWorkingSetSize: size_t,
-        WorkingSetSize: size_t,
-        QuotaPeakPagedPoolUsage: size_t,
-        QuotaPagedPoolUsage: size_t,
-        QuotaPeakNonPagedPoolUsage: size_t,
-        QuotaNonPagedPoolUsage: size_t,
-        PagefileUsage: size_t,
-        PeakPagefileUsage: size_t,
-    }
-    #[allow(non_camel_case_types)]
-    type PPROCESS_MEMORY_COUNTERS = *mut PROCESS_MEMORY_COUNTERS;
-    #[link(name = "psapi")]
-    extern "system" {
-        fn GetCurrentProcess() -> HANDLE;
-        fn GetProcessMemoryInfo(
-            Process: HANDLE,
-            ppsmemCounters: PPROCESS_MEMORY_COUNTERS,
-            cb: DWORD,
-        ) -> BOOL;
-    }
-    let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { mem::zeroed() };
-    pmc.cb = mem::size_of_val(&pmc) as DWORD;
-    match unsafe { GetProcessMemoryInfo(GetCurrentProcess(), &mut pmc, pmc.cb) } {
+    use std::mem::{self, MaybeUninit};
+    use winapi::shared::minwindef::DWORD;
+    use winapi::um::processthreadsapi::GetCurrentProcess;
+    use winapi::um::psapi::{GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS};
+
+    let mut pmc = MaybeUninit::<PROCESS_MEMORY_COUNTERS>::uninit();
+    match unsafe {
+        GetProcessMemoryInfo(GetCurrentProcess(), pmc.as_mut_ptr(), mem::size_of_val(&pmc) as DWORD)
+    } {
         0 => None,
-        _ => Some(pmc.WorkingSetSize as usize),
+        _ => {
+            let pmc = unsafe { pmc.assume_init() };
+            Some(pmc.WorkingSetSize as usize)
+        }
     }
 }
diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs
index 8b85d97..ee3f88f 100644
--- a/src/librustc_data_structures/sharded.rs
+++ b/src/librustc_data_structures/sharded.rs
@@ -137,6 +137,20 @@
     }
 }
 
+pub trait IntoPointer {
+    /// Returns a pointer which outlives `self`.
+    fn into_pointer(&self) -> *const ();
+}
+
+impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
+    pub fn contains_pointer_to<T: Hash + IntoPointer>(&self, value: &T) -> bool {
+        let hash = make_hash(&value);
+        let shard = self.get_shard_by_hash(hash).lock();
+        let value = value.into_pointer();
+        shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some()
+    }
+}
+
 #[inline]
 fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
     let mut state = FxHasher::default();
diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs
index b29ffd7..08706aa 100644
--- a/src/librustc_data_structures/sorted_map.rs
+++ b/src/librustc_data_structures/sorted_map.rs
@@ -132,7 +132,7 @@
         R: RangeBounds<K>,
     {
         let (start, end) = self.range_slice_indices(range);
-        (&self.data[start..end])
+        &self.data[start..end]
     }
 
     #[inline]
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index ed742ed..b856e5d 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -10,7 +10,6 @@
 crate-type = ["dylib"]
 
 [dependencies]
-graphviz = { path = "../libgraphviz" }
 lazy_static = "1.0"
 log = "0.4"
 env_logger = { version = "0.7", default-features = false }
@@ -18,7 +17,7 @@
 rustc_target = { path = "../librustc_target" }
 rustc_lint = { path = "../librustc_lint" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
@@ -30,9 +29,11 @@
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
-rustc_resolve = { path = "../librustc_resolve" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
+
 [features]
 llvm = ['rustc_interface/llvm']
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index dece0a5..019ff43 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -23,10 +23,7 @@
 
 pub extern crate rustc_plugin_impl as plugin;
 
-//use rustc_resolve as resolve;
-use errors::{registry::Registry, PResult};
-use rustc::lint;
-use rustc::lint::Lint;
+use rustc::lint::{Lint, LintId};
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::config::nightly_options;
 use rustc::session::config::{ErrorOutputType, Input, OutputType, PrintRequest};
@@ -37,10 +34,12 @@
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::profiling::print_time_passes_entry;
 use rustc_data_structures::sync::SeqCst;
+use rustc_errors::{registry::Registry, PResult};
 use rustc_feature::{find_gated_cfg, UnstableFeatures};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::get_builtin_codegen_backend;
 use rustc_interface::{interface, Queries};
+use rustc_lint::LintStore;
 use rustc_metadata::locator;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
@@ -369,7 +368,7 @@
                 queries.global_ctxt()?.peek_mut().enter(|tcx| {
                     let result = tcx.analysis(LOCAL_CRATE);
 
-                    sess.time("save analysis", || {
+                    sess.time("save_analysis", || {
                         save::process_crate(
                             tcx,
                             &expanded_crate,
@@ -389,6 +388,7 @@
                 })?;
             } else {
                 // Drop AST after creating GlobalCtxt to free memory
+                let _timer = sess.prof.generic_activity("drop_ast");
                 mem::drop(queries.expansion()?.take());
             }
 
@@ -413,6 +413,7 @@
         })?;
 
         if let Some(linker) = linker {
+            let _timer = sess.timer("link");
             linker.link()?
         }
 
@@ -513,15 +514,10 @@
 
 #[cfg(windows)]
 fn stdout_isatty() -> bool {
-    type DWORD = u32;
-    type BOOL = i32;
-    type HANDLE = *mut u8;
-    type LPDWORD = *mut u32;
-    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
-    extern "system" {
-        fn GetStdHandle(which: DWORD) -> HANDLE;
-        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
-    }
+    use winapi::um::consoleapi::GetConsoleMode;
+    use winapi::um::processenv::GetStdHandle;
+    use winapi::um::winbase::STD_OUTPUT_HANDLE;
+
     unsafe {
         let handle = GetStdHandle(STD_OUTPUT_HANDLE);
         let mut out = 0;
@@ -809,7 +805,7 @@
     );
 }
 
-fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) {
+fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
     println!(
         "
 Available lint options:
@@ -830,8 +826,8 @@
     }
 
     fn sort_lint_groups(
-        lints: Vec<(&'static str, Vec<lint::LintId>, bool)>,
-    ) -> Vec<(&'static str, Vec<lint::LintId>)> {
+        lints: Vec<(&'static str, Vec<LintId>, bool)>,
+    ) -> Vec<(&'static str, Vec<LintId>)> {
         let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
         lints.sort_by_key(|l| l.0);
         lints
@@ -890,7 +886,7 @@
     println!("    {}  {}", padded("----"), "---------");
     println!("    {}  {}", padded("warnings"), "all lints that are set to issue warnings");
 
-    let print_lint_groups = |lints: Vec<(&'static str, Vec<lint::LintId>)>| {
+    let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>| {
         for (name, to) in lints {
             let name = name.to_lowercase().replace("_", "-");
             let desc = to
@@ -1134,7 +1130,7 @@
 /// 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>() {
+        if value.is::<rustc_errors::FatalErrorMarker>() {
             ErrorReported
         } else {
             panic::resume_unwind(value);
@@ -1163,22 +1159,21 @@
     // Separate the output with an empty line
     eprintln!();
 
-    let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
-        errors::ColorConfig::Auto,
+    let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
+        rustc_errors::ColorConfig::Auto,
         None,
         false,
         false,
         None,
         false,
     ));
-    let handler = errors::Handler::with_emitter(true, None, emitter);
+    let handler = rustc_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>() {
-        let d = errors::Diagnostic::new(errors::Level::Bug, "unexpected panic");
+    if !info.payload().is::<rustc_errors::ExplicitBug>() {
+        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
         handler.emit_diagnostic(&d);
-        handler.abort_if_errors_and_should_abort();
     }
 
     let mut xs: Vec<Cow<'static, str>> = vec![
@@ -1214,11 +1209,8 @@
     #[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();
+            winapi::um::debugapi::DebugBreak();
         }
     }
 }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 8804a05..6ef6dcf 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -429,7 +429,6 @@
         PpmSource(s) => {
             // Silently ignores an identified node.
             let out = &mut out;
-            let src = src.clone();
             call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
                 debug!("pretty printing source code {:?}", s);
                 let sess = annotation.sess();
@@ -447,7 +446,6 @@
 
         PpmHir(s) => {
             let out = &mut out;
-            let src = src.clone();
             call_with_pp_support_hir(&s, tcx, move |annotation, krate| {
                 debug!("pretty printing source code {:?}", s);
                 let sess = annotation.sess();
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 272147e..180ccb1 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -414,6 +414,7 @@
 E0743: include_str!("./error_codes/E0743.md"),
 E0744: include_str!("./error_codes/E0744.md"),
 E0745: include_str!("./error_codes/E0745.md"),
+E0746: include_str!("./error_codes/E0746.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0038.md b/src/librustc_error_codes/error_codes/E0038.md
index 25e380b..b2cc2a2 100644
--- a/src/librustc_error_codes/error_codes/E0038.md
+++ b/src/librustc_error_codes/error_codes/E0038.md
@@ -136,7 +136,7 @@
 generates does not grow drastically, since the compiler will only generate an
 implementation if the function is called with unparametrized substitutions
 (i.e., substitutions where none of the substituted types are themselves
-parametrized).
+parameterized).
 
 However, with trait objects we have to make a table containing _every_ object
 that implements the trait. Now, if it has type parameters, we need to add
diff --git a/src/librustc_error_codes/error_codes/E0084.md b/src/librustc_error_codes/error_codes/E0084.md
index 2388bc6..38ce9b4 100644
--- a/src/librustc_error_codes/error_codes/E0084.md
+++ b/src/librustc_error_codes/error_codes/E0084.md
@@ -20,7 +20,7 @@
 }
 ```
 
-or you remove the integer represention of your enum:
+or you remove the integer representation of your enum:
 
 ```
 enum NightsWatch {}
diff --git a/src/librustc_error_codes/error_codes/E0170.md b/src/librustc_error_codes/error_codes/E0170.md
index 4b870db..9678cd1 100644
--- a/src/librustc_error_codes/error_codes/E0170.md
+++ b/src/librustc_error_codes/error_codes/E0170.md
@@ -1,3 +1,24 @@
+A pattern binding is using the same name as one of the variants of a type.
+
+Erroneous code example:
+
+```compile_fail,E0170
+# #![deny(warnings)]
+enum Method {
+    GET,
+    POST,
+}
+
+fn is_empty(s: Method) -> bool {
+    match s {
+        GET => true,
+        _ => false
+    }
+}
+
+fn main() {}
+```
+
 Enum variants are qualified by default. For example, given this type:
 
 ```
diff --git a/src/librustc_error_codes/error_codes/E0184.md b/src/librustc_error_codes/error_codes/E0184.md
index e7fa8df..4624f9e 100644
--- a/src/librustc_error_codes/error_codes/E0184.md
+++ b/src/librustc_error_codes/error_codes/E0184.md
@@ -1,6 +1,20 @@
-Explicitly implementing both Drop and Copy for a type is currently disallowed.
-This feature can make some sense in theory, but the current implementation is
-incorrect and can lead to memory unsafety (see [issue #20126][iss20126]), so
-it has been disabled for now.
+The `Copy` trait was implemented on a type with a `Drop` implementation.
+
+Erroneous code example:
+
+```compile_fail,E0184
+#[derive(Copy)]
+struct Foo; // error!
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+    }
+}
+```
+
+Explicitly implementing both `Drop` and `Copy` trait on a type is currently
+disallowed. This feature can make some sense in theory, but the current
+implementation is incorrect and can lead to memory unsafety (see
+[issue #20126][iss20126]), so it has been disabled for now.
 
 [iss20126]: https://github.com/rust-lang/rust/issues/20126
diff --git a/src/librustc_error_codes/error_codes/E0185.md b/src/librustc_error_codes/error_codes/E0185.md
index f0ad2af..944a93e 100644
--- a/src/librustc_error_codes/error_codes/E0185.md
+++ b/src/librustc_error_codes/error_codes/E0185.md
@@ -2,7 +2,7 @@
 implementation of the trait declared the same function to be a method (i.e., to
 take a `self` parameter).
 
-Here's an example of this error:
+Erroneous code example:
 
 ```compile_fail,E0185
 trait Foo {
@@ -17,3 +17,19 @@
     fn foo(&self) {}
 }
 ```
+
+When a type implements a trait's associated function, it has to use the same
+signature. So in this case, since `Foo::foo` does not take any argument and
+does not return anything, its implementation on `Bar` should be the same:
+
+```
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo() {} // ok!
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0186.md b/src/librustc_error_codes/error_codes/E0186.md
index 9135d5c..7db1e84 100644
--- a/src/librustc_error_codes/error_codes/E0186.md
+++ b/src/librustc_error_codes/error_codes/E0186.md
@@ -2,7 +2,7 @@
 `self` parameter), but an implementation of the trait declared the same function
 to be static.
 
-Here's an example of this error:
+Erroneous code example:
 
 ```compile_fail,E0186
 trait Foo {
@@ -17,3 +17,19 @@
     fn foo() {}
 }
 ```
+
+When a type implements a trait's associated function, it has to use the same
+signature. So in this case, since `Foo::foo` takes `self` as argument and
+does not return anything, its implementation on `Bar` should be the same:
+
+```
+trait Foo {
+    fn foo(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(&self) {} // ok!
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0191.md b/src/librustc_error_codes/error_codes/E0191.md
index b79196f..46b773b 100644
--- a/src/librustc_error_codes/error_codes/E0191.md
+++ b/src/librustc_error_codes/error_codes/E0191.md
@@ -1,5 +1,6 @@
-Trait objects need to have all associated types specified. Erroneous code
-example:
+An associated type wasn't specified for a trait object.
+
+Erroneous code example:
 
 ```compile_fail,E0191
 trait Trait {
@@ -10,8 +11,9 @@
                   //        the trait `Trait`) must be specified
 ```
 
-Please verify you specified all associated types of the trait and that you
-used the right trait. Example:
+Trait objects need to have all associated types specified. Please verify that
+all associated types of the trait were specified and the correct trait was used.
+Example:
 
 ```
 trait Trait {
diff --git a/src/librustc_error_codes/error_codes/E0192.md b/src/librustc_error_codes/error_codes/E0192.md
index 3330886..5fd951b 100644
--- a/src/librustc_error_codes/error_codes/E0192.md
+++ b/src/librustc_error_codes/error_codes/E0192.md
@@ -1,3 +1,19 @@
+A negative impl was added on a trait implementation.
+
+Erroneous code example:
+
+```compile_fail,E0192
+trait Trait {
+    type Bar;
+}
+
+struct Foo;
+
+impl !Trait for Foo { } //~ ERROR E0192
+
+fn main() {}
+```
+
 Negative impls are only allowed for auto traits. For more
 information see the [opt-in builtin traits RFC][RFC 19].
 
diff --git a/src/librustc_error_codes/error_codes/E0195.md b/src/librustc_error_codes/error_codes/E0195.md
index 3606521..b8c313d 100644
--- a/src/librustc_error_codes/error_codes/E0195.md
+++ b/src/librustc_error_codes/error_codes/E0195.md
@@ -1,4 +1,5 @@
-Your method's lifetime parameters do not match the trait declaration.
+The lifetime parameters of the method do not match the trait declaration.
+
 Erroneous code example:
 
 ```compile_fail,E0195
@@ -16,7 +17,7 @@
 }
 ```
 
-The lifetime constraint `'b` for bar() implementation does not match the
+The lifetime constraint `'b` for `bar()` implementation does not match the
 trait declaration. Ensure lifetime declarations match exactly in both trait
 declaration and implementation. Example:
 
diff --git a/src/librustc_error_codes/error_codes/E0197.md b/src/librustc_error_codes/error_codes/E0197.md
index 0d91157..c142b8f 100644
--- a/src/librustc_error_codes/error_codes/E0197.md
+++ b/src/librustc_error_codes/error_codes/E0197.md
@@ -1,13 +1,20 @@
+An inherent implementation was marked unsafe.
+
+Erroneous code example:
+
+```compile_fail,E0197
+struct Foo;
+
+unsafe impl Foo { } // error!
+```
+
 Inherent implementations (one that do not implement a trait but provide
 methods associated with a type) are always safe because they are not
 implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
 implementation will resolve this error.
 
-```compile_fail,E0197
+```
 struct Foo;
 
-// this will cause this error
-unsafe impl Foo { }
-// converting it to this will fix it
-impl Foo { }
+impl Foo { } // ok!
 ```
diff --git a/src/librustc_error_codes/error_codes/E0198.md b/src/librustc_error_codes/error_codes/E0198.md
index 6504d60..687214a 100644
--- a/src/librustc_error_codes/error_codes/E0198.md
+++ b/src/librustc_error_codes/error_codes/E0198.md
@@ -1,17 +1,18 @@
+A negative implementation was marked as unsafe.
+
+Erroneous code example:
+
+```compile_fail
+struct Foo;
+
+unsafe impl !Clone for Foo { } // error!
+```
+
 A negative implementation is one that excludes a type from implementing a
 particular trait. Not being able to use a trait is always a safe operation,
 so negative implementations are always safe and never need to be marked as
 unsafe.
 
-```compile_fail
-#![feature(optin_builtin_traits)]
-
-struct Foo;
-
-// unsafe is unnecessary
-unsafe impl !Clone for Foo { }
-```
-
 This will compile:
 
 ```ignore (ignore auto_trait future compatibility warning)
diff --git a/src/librustc_error_codes/error_codes/E0199.md b/src/librustc_error_codes/error_codes/E0199.md
index d0c12dc..88130e8 100644
--- a/src/librustc_error_codes/error_codes/E0199.md
+++ b/src/librustc_error_codes/error_codes/E0199.md
@@ -1,14 +1,23 @@
-Safe traits should not have unsafe implementations, therefore marking an
-implementation for a safe trait unsafe will cause a compiler error. Removing
-the unsafe marker on the trait noted in the error will resolve this problem.
+A trait implementation was marked as unsafe while the trait is safe.
+
+Erroneous code example:
 
 ```compile_fail,E0199
 struct Foo;
 
 trait Bar { }
 
-// this won't compile because Bar is safe
-unsafe impl Bar for Foo { }
-// this will compile
-impl Bar for Foo { }
+unsafe impl Bar for Foo { } // error!
+```
+
+Safe traits should not have unsafe implementations, therefore marking an
+implementation for a safe trait unsafe will cause a compiler error. Removing
+the unsafe marker on the trait noted in the error will resolve this problem:
+
+```
+struct Foo;
+
+trait Bar { }
+
+impl Bar for Foo { } // ok!
 ```
diff --git a/src/librustc_error_codes/error_codes/E0200.md b/src/librustc_error_codes/error_codes/E0200.md
index 865e914..7245bb5 100644
--- a/src/librustc_error_codes/error_codes/E0200.md
+++ b/src/librustc_error_codes/error_codes/E0200.md
@@ -1,14 +1,23 @@
-Unsafe traits must have unsafe implementations. This error occurs when an
-implementation for an unsafe trait isn't marked as unsafe. This may be resolved
-by marking the unsafe implementation as unsafe.
+An unsafe trait was implemented without an unsafe implementation.
+
+Erroneous code example:
 
 ```compile_fail,E0200
 struct Foo;
 
 unsafe trait Bar { }
 
-// this won't compile because Bar is unsafe and impl isn't unsafe
-impl Bar for Foo { }
-// this will compile
-unsafe impl Bar for Foo { }
+impl Bar for Foo { } // error!
+```
+
+Unsafe traits must have unsafe implementations. This error occurs when an
+implementation for an unsafe trait isn't marked as unsafe. This may be resolved
+by marking the unsafe implementation as unsafe.
+
+```
+struct Foo;
+
+unsafe trait Bar { }
+
+unsafe impl Bar for Foo { } // ok!
 ```
diff --git a/src/librustc_error_codes/error_codes/E0201.md b/src/librustc_error_codes/error_codes/E0201.md
index bdbf02f..0e1a7b7 100644
--- a/src/librustc_error_codes/error_codes/E0201.md
+++ b/src/librustc_error_codes/error_codes/E0201.md
@@ -1,7 +1,7 @@
-It is an error to define two associated items (like methods, associated types,
-associated functions, etc.) with the same identifier.
+Two associated items (like methods, associated types, associated functions,
+etc.) were defined with the same identifier.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0201
 struct Foo(u8);
diff --git a/src/librustc_error_codes/error_codes/E0204.md b/src/librustc_error_codes/error_codes/E0204.md
index 3156901..96e4475 100644
--- a/src/librustc_error_codes/error_codes/E0204.md
+++ b/src/librustc_error_codes/error_codes/E0204.md
@@ -1,21 +1,24 @@
-An attempt to implement the `Copy` trait for a struct failed because one of the
-fields does not implement `Copy`. To fix this, you must implement `Copy` for the
-mentioned field. Note that this may not be possible, as in the example of
+The `Copy` trait was implemented on a type which contains a field that doesn't
+implement the `Copy` trait.
+
+Erroneous code example:
 
 ```compile_fail,E0204
 struct Foo {
-    foo : Vec<u32>,
+    foo: Vec<u32>,
 }
 
-impl Copy for Foo { }
+impl Copy for Foo { } // error!
 ```
 
-This fails because `Vec<T>` does not implement `Copy` for any `T`.
+The `Copy` trait is implemented by default only on primitive types. If your
+type only contains primitive types, you'll be able to implement `Copy` on it.
+Otherwise, it won't be possible.
 
 Here's another example that will fail:
 
 ```compile_fail,E0204
-#[derive(Copy)]
+#[derive(Copy)] // error!
 struct Foo<'a> {
     ty: &'a mut bool,
 }
diff --git a/src/librustc_error_codes/error_codes/E0223.md b/src/librustc_error_codes/error_codes/E0223.md
index 9fe0360..0d49f51 100644
--- a/src/librustc_error_codes/error_codes/E0223.md
+++ b/src/librustc_error_codes/error_codes/E0223.md
@@ -1,5 +1,6 @@
 An attempt was made to retrieve an associated type, but the type was ambiguous.
-For example:
+
+Erroneous code example:
 
 ```compile_fail,E0223
 trait MyTrait {type X; }
diff --git a/src/librustc_error_codes/error_codes/E0225.md b/src/librustc_error_codes/error_codes/E0225.md
index b9820dc..c306e710 100644
--- a/src/librustc_error_codes/error_codes/E0225.md
+++ b/src/librustc_error_codes/error_codes/E0225.md
@@ -1,5 +1,6 @@
-You attempted to use multiple types as bounds for a closure or trait object.
-Rust does not currently support this. A simple example that causes this error:
+Multiple types were used as bounds for a closure or trait object.
+
+Erroneous code example:
 
 ```compile_fail,E0225
 fn main() {
@@ -7,6 +8,8 @@
 }
 ```
 
+Rust does not currently support this.
+
 Auto traits such as Send and Sync are an exception to this rule:
 It's possible to have bounds of one non-builtin trait, plus any number of
 auto traits. For example, the following compiles correctly:
diff --git a/src/librustc_error_codes/error_codes/E0229.md b/src/librustc_error_codes/error_codes/E0229.md
index a8bd341..a8fab05 100644
--- a/src/librustc_error_codes/error_codes/E0229.md
+++ b/src/librustc_error_codes/error_codes/E0229.md
@@ -1,5 +1,7 @@
 An associated type binding was done outside of the type parameter declaration
-and `where` clause. Erroneous code example:
+and `where` clause.
+
+Erroneous code example:
 
 ```compile_fail,E0229
 pub trait Foo {
diff --git a/src/librustc_error_codes/error_codes/E0261.md b/src/librustc_error_codes/error_codes/E0261.md
index 21cf8e7..e326843 100644
--- a/src/librustc_error_codes/error_codes/E0261.md
+++ b/src/librustc_error_codes/error_codes/E0261.md
@@ -1,7 +1,6 @@
-When using a lifetime like `'a` in a type, it must be declared before being
-used.
+An undeclared lifetime was used.
 
-These two examples illustrate the problem:
+Erroneous code example:
 
 ```compile_fail,E0261
 // error, use of undeclared lifetime name `'a`
diff --git a/src/librustc_error_codes/error_codes/E0307.md b/src/librustc_error_codes/error_codes/E0307.md
index 1779e5d..c628d17 100644
--- a/src/librustc_error_codes/error_codes/E0307.md
+++ b/src/librustc_error_codes/error_codes/E0307.md
@@ -36,7 +36,7 @@
 }
 ```
 
-E0307 will be emitted by the compiler when using an invalid reciver type,
+E0307 will be emitted by the compiler when using an invalid receiver type,
 like in the following example:
 
 ```compile_fail,E0307
diff --git a/src/librustc_error_codes/error_codes/E0373.md b/src/librustc_error_codes/error_codes/E0373.md
index 47e3a48..808363e 100644
--- a/src/librustc_error_codes/error_codes/E0373.md
+++ b/src/librustc_error_codes/error_codes/E0373.md
@@ -31,7 +31,7 @@
 may well have disappeared by the time we try to use them. Even if we call
 `thr.join()` within foo (which blocks until `thr` has completed, ensuring the
 stack frame won't disappear), we will not succeed: the compiler cannot prove
-that this behaviour is safe, and so won't let us do it.
+that this behavior is safe, and so won't let us do it.
 
 The solution to this problem is usually to switch to using a `move` closure.
 This approach moves (or copies, where possible) data into the closure, rather
diff --git a/src/librustc_error_codes/error_codes/E0426.md b/src/librustc_error_codes/error_codes/E0426.md
index 15e7fb0..275a83e 100644
--- a/src/librustc_error_codes/error_codes/E0426.md
+++ b/src/librustc_error_codes/error_codes/E0426.md
@@ -8,7 +8,7 @@
 }
 ```
 
-Please verify you spelt or declare the label correctly. Example:
+Please verify you spelled or declared the label correctly. Example:
 
 ```
 'a: loop {
diff --git a/src/librustc_error_codes/error_codes/E0445.md b/src/librustc_error_codes/error_codes/E0445.md
index 9cc62b2..e6a28a9 100644
--- a/src/librustc_error_codes/error_codes/E0445.md
+++ b/src/librustc_error_codes/error_codes/E0445.md
@@ -12,6 +12,8 @@
 pub trait Bar : Foo {} // error: private trait in public interface
 pub struct Bar2<T: Foo>(pub T); // same error
 pub fn foo<T: Foo> (t: T) {} // same error
+
+fn main() {}
 ```
 
 To solve this error, please ensure that the trait is also public. The trait
@@ -26,4 +28,6 @@
 pub trait Bar : Foo {} // ok!
 pub struct Bar2<T: Foo>(pub T); // ok!
 pub fn foo<T: Foo> (t: T) {} // ok!
+
+fn main() {}
 ```
diff --git a/src/librustc_error_codes/error_codes/E0446.md b/src/librustc_error_codes/error_codes/E0446.md
index d014447..77a1834 100644
--- a/src/librustc_error_codes/error_codes/E0446.md
+++ b/src/librustc_error_codes/error_codes/E0446.md
@@ -12,6 +12,8 @@
         Bar(0)
     }
 }
+
+fn main() {}
 ```
 
 To solve this error, please ensure that the type is also public. The type
@@ -27,4 +29,6 @@
         Bar(0)
     }
 }
+
+fn main() {}
 ```
diff --git a/src/librustc_error_codes/error_codes/E0491.md b/src/librustc_error_codes/error_codes/E0491.md
index 1ccaf71..d45663f 100644
--- a/src/librustc_error_codes/error_codes/E0491.md
+++ b/src/librustc_error_codes/error_codes/E0491.md
@@ -3,30 +3,34 @@
 Erroneous code example:
 
 ```compile_fail,E0491
-trait SomeTrait<'a> {
-    type Output;
+struct Foo<'a> {
+    x: fn(&'a i32),
 }
 
-impl<'a, T> SomeTrait<'a> for T {
-    type Output = &'a T; // compile error E0491
+trait Trait<'a, 'b> {
+    type Out;
+}
+
+impl<'a, 'b> Trait<'a, 'b> for usize {
+    type Out = &'a Foo<'b>; // error!
 }
 ```
 
-Here, the problem is that a reference type like `&'a T` is only valid
-if all the data in T outlives the lifetime `'a`. But this impl as written
-is applicable to any lifetime `'a` and any type `T` -- we have no guarantee
-that `T` outlives `'a`. To fix this, you can add a where clause like
-`where T: 'a`.
+Here, the problem is that the compiler cannot be sure that the `'b` lifetime
+will live longer than `'a`, which should be mandatory in order to be sure that
+`Trait::Out` will always have a reference pointing to an existing type. So in
+this case, we just need to tell the compiler than `'b` must outlive `'a`:
 
 ```
-trait SomeTrait<'a> {
-    type Output;
+struct Foo<'a> {
+    x: fn(&'a i32),
 }
 
-impl<'a, T> SomeTrait<'a> for T
-where
-    T: 'a,
-{
-    type Output = &'a T; // compile error E0491
+trait Trait<'a, 'b> {
+    type Out;
+}
+
+impl<'a, 'b: 'a> Trait<'a, 'b> for usize { // we added the lifetime enforcement
+    type Out = &'a Foo<'b>; // it now works!
 }
 ```
diff --git a/src/librustc_error_codes/error_codes/E0527.md b/src/librustc_error_codes/error_codes/E0527.md
index 4bff39d..97ea3126 100644
--- a/src/librustc_error_codes/error_codes/E0527.md
+++ b/src/librustc_error_codes/error_codes/E0527.md
@@ -17,8 +17,6 @@
 array. Additional elements can be matched with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b, ..] => { // ok!
diff --git a/src/librustc_error_codes/error_codes/E0528.md b/src/librustc_error_codes/error_codes/E0528.md
index 4b6ea24..54c2c4d 100644
--- a/src/librustc_error_codes/error_codes/E0528.md
+++ b/src/librustc_error_codes/error_codes/E0528.md
@@ -4,8 +4,6 @@
 Example of erroneous code:
 
 ```compile_fail,E0528
-#![feature(slice_patterns)]
-
 let r = &[1, 2];
 match r {
     &[a, b, c, rest @ ..] => { // error: pattern requires at least 3
@@ -19,8 +17,6 @@
 requires. You can match an arbitrary number of remaining elements with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4, 5];
 match r {
     &[a, b, c, rest @ ..] => { // ok!
diff --git a/src/librustc_error_codes/error_codes/E0566.md b/src/librustc_error_codes/error_codes/E0566.md
index 62fb66f..3dcd801 100644
--- a/src/librustc_error_codes/error_codes/E0566.md
+++ b/src/librustc_error_codes/error_codes/E0566.md
@@ -2,8 +2,8 @@
 
 Erroneous code example:
 
-```
-#[repr(u32, u64)] // warning!
+```compile_fail,E0566
+#[repr(u32, u64)]
 enum Repr { A }
 ```
 
diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md
index 803a251..bf1f72b 100644
--- a/src/librustc_error_codes/error_codes/E0730.md
+++ b/src/librustc_error_codes/error_codes/E0730.md
@@ -18,8 +18,6 @@
 array. Additional elements can be matched with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b, ..] => { // ok!
diff --git a/src/librustc_error_codes/error_codes/E0746.md b/src/librustc_error_codes/error_codes/E0746.md
new file mode 100644
index 0000000..16b2722
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0746.md
@@ -0,0 +1,138 @@
+Return types cannot be `dyn Trait`s as they must be `Sized`.
+
+Erroneous code example:
+
+```compile_fail,E0277
+# // FIXME: after E0746 is in beta, change the above
+trait T {
+    fn bar(&self);
+}
+struct S(usize);
+impl T for S {
+    fn bar(&self) {}
+}
+
+// Having the trait `T` as return type is invalid because
+// unboxed trait objects do not have a statically known size:
+fn foo() -> dyn T {
+    S(42)
+}
+```
+
+To avoid the error there are a couple of options.
+
+If there is a single type involved, you can use [`impl Trait`]:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+// The compiler will select `S(usize)` as the materialized return type of this
+// function, but callers will only know that the return type implements `T`.
+fn foo() -> impl T {
+    S(42)
+}
+```
+
+If there are multiple types involved, the only way you care to interact with
+them is through the trait's interface, and having to rely on dynamic dispatch
+is acceptable, then you can use [trait objects] with `Box`, or other container
+types like `Rc` or `Arc`:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+struct O(&'static str);
+impl T for O {
+    fn bar(&self) {}
+}
+
+// This now returns a "trait object" and callers are only be able to access
+// associated items from `T`.
+fn foo(x: bool) -> Box<dyn T> {
+    if x {
+        Box::new(S(42))
+    } else {
+        Box::new(O("val"))
+    }
+}
+```
+
+Finally, if you wish to still be able to access the original type, you can
+create a new `enum` with a variant for each type:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+# struct O(&'static str);
+# impl T for O {
+#     fn bar(&self) {}
+# }
+enum E {
+    S(S),
+    O(O),
+}
+
+// The caller can access the original types directly, but it needs to match on
+// the returned `enum E`.
+fn foo(x: bool) -> E {
+    if x {
+        E::S(S(42))
+    } else {
+        E::O(O("val"))
+    }
+}
+```
+
+You can even implement the `trait` on the returned `enum` so the callers
+*don't* have to match on the returned value to invoke the associated items:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+# struct O(&'static str);
+# impl T for O {
+#     fn bar(&self) {}
+# }
+# enum E {
+#     S(S),
+#     O(O),
+# }
+impl T for E {
+    fn bar(&self) {
+        match self {
+            E::S(s) => s.bar(),
+            E::O(o) => o.bar(),
+        }
+    }
+}
+```
+
+If you decide to use trait objects, be aware that these rely on
+[dynamic dispatch], which has performance implications, as the compiler needs
+to emit code that will figure out which method to call *at runtime* instead of
+during compilation. Using trait objects we are trading flexibility for
+performance.
+
+[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits
+[trait objects]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
+[dynamic dispatch]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch
diff --git a/src/librustc_error_codes/lib.rs b/src/librustc_error_codes/lib.rs
index 14210fd..f051fdd 100644
--- a/src/librustc_error_codes/lib.rs
+++ b/src/librustc_error_codes/lib.rs
@@ -6,16 +6,8 @@
         pub static DIAGNOSTICS: &[(&str, &str)] = &[
             $( (stringify!($ecode), $message), )*
         ];
-
-        $(
-            pub const $ecode: () = ();
-        )*
-        $(
-            pub const $code: () = ();
-        )*
     )
 }
 
 mod error_codes;
-
-pub use error_codes::*;
+pub use error_codes::DIAGNOSTICS;
diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml
index 0d09896..01ea806 100644
--- a/src/librustc_errors/Cargo.toml
+++ b/src/librustc_errors/Cargo.toml
@@ -19,3 +19,6 @@
 termcolor = "1.0"
 annotate-snippets = "0.6.1"
 term_size = "0.3.1"
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] }
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 7413cef..009ab6a 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -196,7 +196,7 @@
     ) {
         let converter = DiagnosticConverter {
             source_map: self.source_map.clone(),
-            level: level.clone(),
+            level: *level,
             message,
             code: code.clone(),
             msp: msp.clone(),
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 79ec9ad..3c217c1 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -385,3 +385,19 @@
         }
     }
 }
+
+#[macro_export]
+macro_rules! struct_span_err {
+    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+        $session.struct_span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::error_code!($code),
+        )
+    })
+}
+
+#[macro_export]
+macro_rules! error_code {
+    ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
+}
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 526b4e2..b0e0cb6 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1476,6 +1476,15 @@
             None => return Ok(()),
         };
 
+        // Render the replacements for each suggestion
+        let suggestions = suggestion.splice_lines(&**sm);
+
+        if suggestions.is_empty() {
+            // Suggestions coming from macros can have malformed spans. This is a heavy handed
+            // approach to avoid ICEs by ignoring the suggestion outright.
+            return Ok(());
+        }
+
         let mut buffer = StyledBuffer::new();
 
         // Render the suggestion message
@@ -1492,9 +1501,6 @@
             Some(Style::HeaderMsg),
         );
 
-        // Render the replacements for each suggestion
-        let suggestions = suggestion.splice_lines(&**sm);
-
         let mut row_num = 2;
         let mut notice_capitalization = false;
         for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) {
@@ -1505,7 +1511,9 @@
             let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
                 && complete.lines().count() == 1;
 
-            let lines = sm.span_to_lines(parts[0].span).unwrap();
+            let lines = sm
+                .span_to_lines(parts[0].span)
+                .expect("span_to_lines failed when emitting suggestion");
 
             assert!(!lines.lines.is_empty());
 
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 2279ed8..17b2934 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -10,6 +10,7 @@
 
 pub use emitter::ColorConfig;
 
+use log::debug;
 use Level::*;
 
 use emitter::{is_case_difference, Emitter, EmitterWriter};
@@ -174,17 +175,27 @@
 
         self.substitutions
             .iter()
+            .filter(|subst| {
+                // Suggestions coming from macros can have malformed spans. This is a heavy
+                // handed approach to avoid ICEs by ignoring the suggestion outright.
+                let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err());
+                if invalid {
+                    debug!("splice_lines: suggestion contains an invalid span: {:?}", subst);
+                }
+                !invalid
+            })
             .cloned()
-            .map(|mut substitution| {
+            .filter_map(|mut substitution| {
                 // Assumption: all spans are in the same file, and all spans
                 // are disjoint. Sort in ascending order.
                 substitution.parts.sort_by_key(|part| part.span.lo());
 
                 // Find the bounding span.
-                let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap();
-                let hi = substitution.parts.iter().map(|part| part.span.hi()).min().unwrap();
+                let lo = substitution.parts.iter().map(|part| part.span.lo()).min()?;
+                let hi = substitution.parts.iter().map(|part| part.span.hi()).max()?;
                 let bounding_span = Span::with_root_ctxt(lo, hi);
-                let lines = cm.span_to_lines(bounding_span).unwrap();
+                // The different spans might belong to different contexts, if so ignore suggestion.
+                let lines = cm.span_to_lines(bounding_span).ok()?;
                 assert!(!lines.lines.is_empty());
 
                 // To build up the result, we do this for each span:
@@ -234,7 +245,7 @@
                 while buf.ends_with('\n') {
                     buf.pop();
                 }
-                (buf, substitution.parts, only_capitalization)
+                Some((buf, substitution.parts, only_capitalization))
             })
             .collect()
     }
@@ -278,7 +289,6 @@
     err_count: usize,
     deduplicated_err_count: usize,
     emitter: Box<dyn Emitter + sync::Send>,
-    continue_after_error: bool,
     delayed_span_bugs: Vec<Diagnostic>,
 
     /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
@@ -402,7 +412,6 @@
                 err_count: 0,
                 deduplicated_err_count: 0,
                 emitter,
-                continue_after_error: true,
                 delayed_span_bugs: Vec::new(),
                 taught_diagnostics: Default::default(),
                 emitted_diagnostic_codes: Default::default(),
@@ -412,10 +421,6 @@
         }
     }
 
-    pub fn set_continue_after_error(&self, continue_after_error: bool) {
-        self.inner.borrow_mut().continue_after_error = continue_after_error;
-    }
-
     // This is here to not allow mutation of flags;
     // as of this writing it's only used in tests in librustc.
     pub fn can_emit_warnings(&self) -> bool {
@@ -672,10 +677,6 @@
         self.inner.borrow_mut().abort_if_errors()
     }
 
-    pub fn abort_if_errors_and_should_abort(&self) {
-        self.inner.borrow_mut().abort_if_errors_and_should_abort()
-    }
-
     /// `true` if we haven't taught a diagnostic with this code already.
     /// The caller must then teach the user about such a diagnostic.
     ///
@@ -696,7 +697,6 @@
     fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
         let mut inner = self.inner.borrow_mut();
         inner.emit_diagnostic(diag.set_span(sp));
-        inner.abort_if_errors_and_should_abort();
     }
 
     pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
@@ -830,14 +830,6 @@
         self.has_errors() || !self.delayed_span_bugs.is_empty()
     }
 
-    fn abort_if_errors_and_should_abort(&mut self) {
-        self.emit_stashed_diagnostics();
-
-        if self.has_errors() && !self.continue_after_error {
-            FatalError.raise();
-        }
-    }
-
     fn abort_if_errors(&mut self) {
         self.emit_stashed_diagnostics();
 
@@ -853,7 +845,6 @@
 
     fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
         self.emit_diagnostic(diag.set_span(sp));
-        self.abort_if_errors_and_should_abort();
     }
 
     fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
diff --git a/src/librustc_errors/lock.rs b/src/librustc_errors/lock.rs
index 198a9c1..a734720 100644
--- a/src/librustc_errors/lock.rs
+++ b/src/librustc_errors/lock.rs
@@ -12,31 +12,14 @@
 use std::any::Any;
 
 #[cfg(windows)]
-#[allow(nonstandard_style)]
 pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
     use std::ffi::CString;
     use std::io;
 
-    type LPSECURITY_ATTRIBUTES = *mut u8;
-    type BOOL = i32;
-    type LPCSTR = *const u8;
-    type HANDLE = *mut u8;
-    type DWORD = u32;
-
-    const INFINITE: DWORD = !0;
-    const WAIT_OBJECT_0: DWORD = 0;
-    const WAIT_ABANDONED: DWORD = 0x00000080;
-
-    extern "system" {
-        fn CreateMutexA(
-            lpMutexAttributes: LPSECURITY_ATTRIBUTES,
-            bInitialOwner: BOOL,
-            lpName: LPCSTR,
-        ) -> HANDLE;
-        fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
-        fn ReleaseMutex(hMutex: HANDLE) -> BOOL;
-        fn CloseHandle(hObject: HANDLE) -> BOOL;
-    }
+    use winapi::shared::ntdef::HANDLE;
+    use winapi::um::handleapi::CloseHandle;
+    use winapi::um::synchapi::{CreateMutexA, ReleaseMutex, WaitForSingleObject};
+    use winapi::um::winbase::{INFINITE, WAIT_ABANDONED, WAIT_OBJECT_0};
 
     struct Handle(HANDLE);
 
@@ -65,7 +48,7 @@
         //
         // This will silently create one if it doesn't already exist, or it'll
         // open up a handle to one if it already exists.
-        let mutex = CreateMutexA(std::ptr::null_mut(), 0, cname.as_ptr() as *const u8);
+        let mutex = CreateMutexA(std::ptr::null_mut(), 0, cname.as_ptr());
         if mutex.is_null() {
             panic!(
                 "failed to create global mutex named `{}`: {}",
diff --git a/src/librustc_expand/Cargo.toml b/src/librustc_expand/Cargo.toml
index f9c15fb..d04dd07 100644
--- a/src/librustc_expand/Cargo.toml
+++ b/src/librustc_expand/Cargo.toml
@@ -14,10 +14,12 @@
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 log = "0.4"
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
+rustc_ast_passes = { path = "../librustc_ast_passes" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index fe08c85..52ba14d 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -1,9 +1,15 @@
 use crate::expand::{self, AstFragment, Invocation};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{self, Lrc};
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
 use rustc_span::edition::Edition;
+use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
+use smallvec::{smallvec, SmallVec};
 use syntax::ast::{self, Attribute, Name, NodeId, PatKind};
 use syntax::attr::{self, Deprecation, HasAttrs, Stability};
 use syntax::mut_visit::{self, MutVisitor};
@@ -13,13 +19,6 @@
 use syntax::tokenstream::{self, TokenStream};
 use syntax::visit::Visitor;
 
-use errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{self, Lrc};
-use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
-use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
-
 use std::default::Default;
 use std::iter;
 use std::path::PathBuf;
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index 6eead11..3254d0c 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -5,6 +5,8 @@
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
 use rustc_parse::configure;
 use rustc_parse::parser::Parser;
@@ -16,20 +18,16 @@
 use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
 use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
 use syntax::attr::{self, is_builtin_attr, HasAttrs};
-use syntax::feature_gate::{self, feature_err};
 use syntax::mut_visit::*;
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::sess::ParseSess;
+use syntax::sess::{feature_err, ParseSess};
 use syntax::token;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::util::map_in_place::MapInPlace;
 use syntax::visit::{self, Visitor};
 
-use errors::{Applicability, FatalError, PResult};
 use smallvec::{smallvec, SmallVec};
-
-use rustc_data_structures::sync::Lrc;
 use std::io::ErrorKind;
 use std::ops::DerefMut;
 use std::path::PathBuf;
@@ -1063,7 +1061,7 @@
     fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
-            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
+            rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.parse_sess, features);
             validate_attr::check_meta(self.cx.parse_sess, attr);
 
             // macros are expanded before any lint passes so this warning has to be hardcoded
diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs
index feba7f6..4fe7c26 100644
--- a/src/librustc_expand/lib.rs
+++ b/src/librustc_expand/lib.rs
@@ -13,7 +13,7 @@
 #[macro_export]
 macro_rules! panictry {
     ($e:expr) => {{
-        use errors::FatalError;
+        use rustc_errors::FatalError;
         use std::result::Result::{Err, Ok};
         match $e {
             Ok(e) => e,
diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs
index 992764a..47865b2 100644
--- a/src/librustc_expand/mbe/macro_check.rs
+++ b/src/librustc_expand/mbe/macro_check.rs
@@ -106,14 +106,14 @@
 //! bound.
 use crate::mbe::{KleeneToken, TokenTree};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
+use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym};
+use rustc_span::{symbol::Ident, MultiSpan, Span};
 use syntax::ast::NodeId;
-use syntax::early_buffered_lints::META_VARIABLE_MISUSE;
-use syntax::sess::ParseSess;
 use syntax::token::{DelimToken, Token, TokenKind};
 
-use rustc_data_structures::fx::FxHashMap;
-use rustc_span::{symbol::Ident, MultiSpan, Span};
 use smallvec::SmallVec;
 
 /// Stack represented as linked list.
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index c0e34a3..246f660 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -85,7 +85,7 @@
 use syntax::token::{self, DocComment, Nonterminal, Token};
 use syntax::tokenstream::TokenStream;
 
-use errors::{FatalError, PResult};
+use rustc_errors::{FatalError, PResult};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 
@@ -696,7 +696,7 @@
                         if parser.token.span.is_dummy() {
                             parser.token.span
                         } else {
-                            sess.source_map().next_point(parser.token.span)
+                            parser.token.span.shrink_to_hi()
                         },
                     ),
                     "missing tokens in macro arguments",
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 6e96534..d72317a 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -8,6 +8,9 @@
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult};
 use crate::mbe::transcribe::transcribe;
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
 use rustc_parse::Directory;
@@ -22,17 +25,11 @@
 use syntax::token::{self, NtTT, Token, TokenKind::*};
 use syntax::tokenstream::{DelimSpan, TokenStream};
 
-use errors::{DiagnosticBuilder, FatalError};
 use log::debug;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::{mem, slice};
 
-use errors::Applicability;
-
 const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
                                         `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
                                         `literal`, `path`, `meta`, `tt`, `item` and `vis`";
diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs
index 4fd68a8..104a523 100644
--- a/src/librustc_expand/mbe/transcribe.rs
+++ b/src/librustc_expand/mbe/transcribe.rs
@@ -2,19 +2,17 @@
 use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::pluralize;
+use rustc_span::hygiene::{ExpnId, Transparency};
+use rustc_span::Span;
 use syntax::ast::{Ident, Mac};
 use syntax::mut_visit::{self, MutVisitor};
 use syntax::token::{self, NtTT, Token};
 use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 
 use smallvec::{smallvec, SmallVec};
-
-use errors::pluralize;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
-use rustc_span::hygiene::{ExpnId, Transparency};
-use rustc_span::Span;
-
 use std::mem;
 
 // A Marker adds the given mark to the syntax context.
diff --git a/src/librustc_expand/parse/lexer/tests.rs b/src/librustc_expand/parse/lexer/tests.rs
index 835f0b0..2ef81d8 100644
--- a/src/librustc_expand/parse/lexer/tests.rs
+++ b/src/librustc_expand/parse/lexer/tests.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{emitter::EmitterWriter, Handler};
 use rustc_parse::lexer::StringReader;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::symbol::Symbol;
@@ -8,7 +9,6 @@
 use syntax::util::comments::is_doc_comment;
 use syntax::with_default_globals;
 
-use errors::{emitter::EmitterWriter, Handler};
 use std::io;
 use std::path::PathBuf;
 
diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs
index 25cd5da..b79e289 100644
--- a/src/librustc_expand/parse/tests.rs
+++ b/src/librustc_expand/parse/tests.rs
@@ -1,6 +1,6 @@
 use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
 
-use errors::PResult;
+use rustc_errors::PResult;
 use rustc_parse::new_parser_from_source_str;
 use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::{kw, sym, Symbol};
diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs
index 25e2bbb..cb6249e 100644
--- a/src/librustc_expand/proc_macro.rs
+++ b/src/librustc_expand/proc_macro.rs
@@ -1,15 +1,14 @@
 use crate::base::{self, *};
 use crate::proc_macro_server;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, FatalError};
 use rustc_span::symbol::sym;
+use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
-use syntax::errors::{Applicability, FatalError};
 use syntax::token;
 use syntax::tokenstream::{self, TokenStream};
 
-use rustc_data_structures::sync::Lrc;
-use rustc_span::{Span, DUMMY_SP};
-
 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
 
 pub struct BangProcMacro {
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index cf5749f..d441613 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -1,5 +1,7 @@
 use crate::base::ExtCtxt;
 
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::Diagnostic;
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -11,9 +13,6 @@
 use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
 use syntax::util::comments;
 
-use errors::Diagnostic;
-use rustc_data_structures::sync::Lrc;
-
 use pm::bridge::{server, TokenTree};
 use pm::{Delimiter, Level, LineColumn, Spacing};
 use std::ops::Bound;
@@ -265,13 +264,13 @@
     }
 }
 
-impl ToInternal<errors::Level> for Level {
-    fn to_internal(self) -> errors::Level {
+impl ToInternal<rustc_errors::Level> for Level {
+    fn to_internal(self) -> rustc_errors::Level {
         match self {
-            Level::Error => errors::Level::Error,
-            Level::Warning => errors::Level::Warning,
-            Level::Note => errors::Level::Note,
-            Level::Help => errors::Level::Help,
+            Level::Error => rustc_errors::Level::Error,
+            Level::Warning => rustc_errors::Level::Warning,
+            Level::Note => rustc_errors::Level::Note,
+            Level::Help => rustc_errors::Level::Help,
             _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
         }
     }
diff --git a/src/librustc_expand/tests.rs b/src/librustc_expand/tests.rs
index 18dc605..82ab74a 100644
--- a/src/librustc_expand/tests.rs
+++ b/src/librustc_expand/tests.rs
@@ -6,9 +6,9 @@
 use syntax::tokenstream::TokenStream;
 use syntax::with_default_globals;
 
-use errors::emitter::EmitterWriter;
-use errors::{Handler, PResult};
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::emitter::EmitterWriter;
+use rustc_errors::{Handler, PResult};
 
 use std::io;
 use std::io::prelude::*;
diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs
index d880fc8..007cee4 100644
--- a/src/librustc_feature/accepted.rs
+++ b/src/librustc_feature/accepted.rs
@@ -257,6 +257,8 @@
     /// Allows relaxing the coherence rules such that
     /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
     (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None),
+    /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
+    (accepted, slice_patterns, "1.42.0", Some(62254), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 8cb1684..6af9b6c 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -192,9 +192,6 @@
     /// Allows using the `unadjusted` ABI; perma-unstable.
     (active, abi_unadjusted, "1.16.0", None, None),
 
-    /// Allows identifying crates that contain sanitizer runtimes.
-    (active, sanitizer_runtime, "1.17.0", None, None),
-
     /// Used to identify crates that contain the profiler runtime.
     (active, profiler_runtime, "1.18.0", None, None),
 
@@ -265,9 +262,6 @@
     /// Allows using non lexical lifetimes (RFC 2094).
     (active, nll, "1.0.0", Some(43234), None),
 
-    /// Allows using slice patterns.
-    (active, slice_patterns, "1.0.0", Some(62254), None),
-
     /// Allows the definition of `const` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(57563), None),
 
@@ -336,7 +330,7 @@
     (active, abi_ptx, "1.15.0", Some(38788), None),
 
     /// Allows the `#[repr(i128)]` attribute for enums.
-    (active, repr128, "1.16.0", Some(35118), None),
+    (active, repr128, "1.16.0", Some(56071), None),
 
     /// Allows `#[link(kind="static-nobundle"...)]`.
     (active, static_nobundle, "1.16.0", Some(37403), None),
@@ -484,7 +478,7 @@
     (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
 
     /// Allows `impl Trait` with multiple unrelated lifetimes.
-    (active, member_constraints, "1.37.0", Some(61977), None),
+    (active, member_constraints, "1.37.0", Some(61997), None),
 
     /// Allows `async || body` closures.
     (active, async_closure, "1.37.0", Some(62290), None),
@@ -534,6 +528,9 @@
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
 
+    /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
+    (active, half_open_range_patterns, "1.41.0", Some(67264), None),
+
     /// Allows using `&mut` in constant functions.
     (active, const_mut_refs, "1.41.0", Some(57349), None),
 
@@ -544,6 +541,12 @@
     /// For example, you can write `x @ Some(y)`.
     (active, bindings_after_at, "1.41.0", Some(65490), None),
 
+    /// Allows `impl const Trait for T` syntax.
+    (active, const_trait_impl, "1.42.0", Some(67792), None),
+
+    /// Allows `T: ?const Trait` syntax in bounds.
+    (active, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -559,4 +562,6 @@
     sym::or_patterns,
     sym::let_chains,
     sym::raw_dylib,
+    sym::const_trait_impl,
+    sym::const_trait_bound_opt_out,
 ];
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index 3cbf96b..a38726e 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -410,11 +410,6 @@
         which contains compiler-rt intrinsics and will never be stable",
     ),
     gated!(
-        sanitizer_runtime, Whitelisted, template!(Word),
-        "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \
-        of a sanitizer and will never be stable",
-    ),
-    gated!(
         profiler_runtime, Whitelisted, template!(Word),
         "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
         which contains the profiler runtime and will never be stable",
diff --git a/src/librustc_feature/lib.rs b/src/librustc_feature/lib.rs
index 71a4642..01546f7 100644
--- a/src/librustc_feature/lib.rs
+++ b/src/librustc_feature/lib.rs
@@ -1,7 +1,8 @@
 //! # Feature gates
 //!
 //! This crate declares the set of past and present unstable features in the compiler.
-//! Feature gate checking itself is done in `libsyntax/feature_gate/check.rs` at the moment.
+//! Feature gate checking itself is done in `librustc_ast_passes/feature_gate.rs`
+//! at the moment.
 //!
 //! Features are enabled in programs via the crate-level attributes of
 //! `#![feature(...)]` with a comma-separated list of features.
diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs
index 1eeedd7..d5b6fe8 100644
--- a/src/librustc_feature/removed.rs
+++ b/src/librustc_feature/removed.rs
@@ -74,6 +74,8 @@
     (removed, pushpop_unsafe, "1.2.0", None, None, None),
     (removed, needs_allocator, "1.4.0", Some(27389), None,
      Some("subsumed by `#![feature(allocator_internals)]`")),
+    /// Allows identifying crates that contain sanitizer runtimes.
+    (removed, sanitizer_runtime, "1.17.0", None, None, None),
     (removed, proc_macro_mod, "1.27.0", Some(54727), None,
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
     (removed, proc_macro_expr, "1.27.0", Some(54727), None,
diff --git a/src/librustc_hir/def_id.rs b/src/librustc_hir/def_id.rs
index f8cacdc..7ee778d 100644
--- a/src/librustc_hir/def_id.rs
+++ b/src/librustc_hir/def_id.rs
@@ -1,7 +1,8 @@
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
+use rustc_serialize::{Decoder, Encoder};
 use std::fmt;
-use std::u32;
+use std::{u32, u64};
 
 rustc_index::newtype_index! {
     pub struct CrateId {
@@ -86,8 +87,18 @@
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for CrateNum {}
-impl rustc_serialize::UseSpecializedDecodable for CrateNum {}
+/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
+/// Therefore, make sure to include the context when encode a `CrateNum`.
+impl rustc_serialize::UseSpecializedEncodable for CrateNum {
+    fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+        e.emit_u32(self.as_u32())
+    }
+}
+impl rustc_serialize::UseSpecializedDecodable for CrateNum {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
+        Ok(CrateNum::from_u32(d.read_u32()?))
+    }
+}
 
 rustc_index::newtype_index! {
     /// A DefIndex is an index into the hir-map for a crate, identifying a
@@ -135,8 +146,21 @@
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for DefId {}
-impl rustc_serialize::UseSpecializedDecodable for DefId {}
+impl rustc_serialize::UseSpecializedEncodable for DefId {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        let krate = u64::from(self.krate.as_u32());
+        let index = u64::from(self.index.as_u32());
+        s.emit_u64((krate << 32) | index)
+    }
+}
+impl rustc_serialize::UseSpecializedDecodable for DefId {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
+        let def_id = d.read_u64()?;
+        let krate = CrateNum::from_u32((def_id >> 32) as u32);
+        let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
+        Ok(DefId { krate, index })
+    }
+}
 
 pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 2303a85..b62a7e4 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -364,6 +364,7 @@
 pub enum TraitBoundModifier {
     None,
     Maybe,
+    MaybeConst,
 }
 
 /// The AST represents all type param bounds as types.
@@ -377,6 +378,13 @@
 }
 
 impl GenericBound<'_> {
+    pub fn trait_def_id(&self) -> Option<DefId> {
+        match self {
+            GenericBound::Trait(data, _) => Some(data.trait_ref.trait_def_id()),
+            _ => None,
+        }
+    }
+
     pub fn span(&self) -> Span {
         match self {
             &GenericBound::Trait(ref t, ..) => t.span,
@@ -905,7 +913,7 @@
     Lit(&'hir Expr<'hir>),
 
     /// A range pattern (e.g., `1..=2` or `1..2`).
-    Range(&'hir Expr<'hir>, &'hir Expr<'hir>, RangeEnd),
+    Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
 
     /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
     ///
@@ -1875,6 +1883,9 @@
     OpaqueTy(GenericBounds<'hir>),
 }
 
+// The name of the associated type for `Fn` return types.
+pub const FN_OUTPUT_NAME: Symbol = sym::Output;
+
 /// Bind a type to an associated type (i.e., `A = Foo`).
 ///
 /// Bindings like `A: Debug` are represented as a special type `A =
@@ -2426,15 +2437,19 @@
     TraitAlias(Generics<'hir>, GenericBounds<'hir>),
 
     /// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
-    Impl(
-        Unsafety,
-        ImplPolarity,
-        Defaultness,
-        Generics<'hir>,
-        Option<TraitRef<'hir>>, // (optional) trait this impl implements
-        &'hir Ty<'hir>,         // self
-        &'hir [ImplItemRef<'hir>],
-    ),
+    Impl {
+        unsafety: Unsafety,
+        polarity: ImplPolarity,
+        defaultness: Defaultness,
+        constness: Constness,
+        generics: Generics<'hir>,
+
+        /// The trait being implemented, if any.
+        of_trait: Option<TraitRef<'hir>>,
+
+        self_ty: &'hir Ty<'hir>,
+        items: &'hir [ImplItemRef<'hir>],
+    },
 }
 
 impl ItemKind<'_> {
@@ -2455,7 +2470,7 @@
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Impl(..) => "impl",
+            ItemKind::Impl { .. } => "impl",
         }
     }
 
@@ -2468,7 +2483,7 @@
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics)
             | ItemKind::Trait(_, _, ref generics, _, _)
-            | ItemKind::Impl(_, _, _, ref generics, _, _, _) => generics,
+            | ItemKind::Impl { ref generics, .. } => generics,
             _ => return None,
         })
     }
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc_hir/intravisit.rs
similarity index 95%
rename from src/librustc/hir/intravisit.rs
rename to src/librustc_hir/intravisit.rs
index edecfd3..539a0ee 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -31,21 +31,18 @@
 //! This order consistency is required in a few places in rustc, for
 //! example generator inference, and possibly also HIR borrowck.
 
-use crate::hir::map::Map;
-
-use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
-use rustc_hir::*;
+use crate::hir::*;
+use crate::hir_id::CRATE_HIR_ID;
+use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
 use rustc_span::Span;
 use syntax::ast::{Attribute, Ident, Label, Name};
+use syntax::walk_list;
 
 pub struct DeepVisitor<'v, V> {
     visitor: &'v mut V,
 }
 
-impl<'v, 'hir, V> DeepVisitor<'v, V>
-where
-    V: Visitor<'hir> + 'v,
-{
+impl<'v, V> DeepVisitor<'v, V> {
     pub fn new(base: &'v mut V) -> Self {
         DeepVisitor { visitor: base }
     }
@@ -122,6 +119,14 @@
     }
 }
 
+/// An abstract representation of the HIR `rustc::hir::map::Map`.
+pub trait Map<'hir> {
+    fn body(&self, id: BodyId) -> &'hir Body<'hir>;
+    fn item(&self, id: HirId) -> &'hir Item<'hir>;
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+}
+
 /// Specifies what nested things a visitor wants to visit. The most
 /// common choice is `OnlyBodies`, which will cause the visitor to
 /// visit fn bodies for fns that it encounters, but skip over nested
@@ -129,7 +134,7 @@
 ///
 /// See the comments on `ItemLikeVisitor` for more details on the overall
 /// visit strategy.
-pub enum NestedVisitorMap<'this, 'tcx> {
+pub enum NestedVisitorMap<'this, M> {
     /// Do not visit any nested things. When you add a new
     /// "non-nested" thing, you will want to audit such uses to see if
     /// they remain valid.
@@ -146,20 +151,20 @@
     /// to use `visit_all_item_likes()` as an outer loop,
     /// and to have the visitor that visits the contents of each item
     /// using this setting.
-    OnlyBodies(&'this Map<'tcx>),
+    OnlyBodies(&'this M),
 
     /// Visits all nested things, including item-likes.
     ///
     /// **This is an unusual choice.** It is used when you want to
     /// process everything within their lexical context. Typically you
     /// kick off the visit by doing `walk_krate()`.
-    All(&'this Map<'tcx>),
+    All(&'this M),
 }
 
-impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> {
+impl<'this, M> NestedVisitorMap<'this, M> {
     /// Returns the map to use for an "intra item-like" thing (if any).
     /// E.g., function body.
-    pub fn intra(self) -> Option<&'this Map<'tcx>> {
+    fn intra(self) -> Option<&'this M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(map) => Some(map),
@@ -169,7 +174,7 @@
 
     /// Returns the map to use for an "item-like" thing (if any).
     /// E.g., item, impl-item.
-    pub fn inter(self) -> Option<&'this Map<'tcx>> {
+    fn inter(self) -> Option<&'this M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(_) => None,
@@ -195,6 +200,8 @@
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
 pub trait Visitor<'v>: Sized {
+    type Map: Map<'v>;
+
     ///////////////////////////////////////////////////////////////////////////
     // Nested items.
 
@@ -214,7 +221,7 @@
     /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
     /// added in the future, we will see the panic in your code and
     /// fix it appropriately.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>;
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map>;
 
     /// Invoked when a nested item is encountered. By default does
     /// nothing unless you override `nested_visit_map` to return other than
@@ -226,10 +233,8 @@
     /// but cannot supply a `Map`; see `nested_visit_map` for advice.
     #[allow(unused_variables)]
     fn visit_nested_item(&mut self, id: ItemId) {
-        let opt_item = self.nested_visit_map().inter().map(|map| map.expect_item(id.id));
-        if let Some(item) = opt_item {
-            self.visit_item(item);
-        }
+        let opt_item = self.nested_visit_map().inter().map(|map| map.item(id.id));
+        walk_list!(self, visit_item, opt_item);
     }
 
     /// Like `visit_nested_item()`, but for trait items. See
@@ -238,9 +243,7 @@
     #[allow(unused_variables)]
     fn visit_nested_trait_item(&mut self, id: TraitItemId) {
         let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
-        if let Some(item) = opt_item {
-            self.visit_trait_item(item);
-        }
+        walk_list!(self, visit_trait_item, opt_item);
     }
 
     /// Like `visit_nested_item()`, but for impl items. See
@@ -249,9 +252,7 @@
     #[allow(unused_variables)]
     fn visit_nested_impl_item(&mut self, id: ImplItemId) {
         let opt_item = self.nested_visit_map().inter().map(|map| map.impl_item(id));
-        if let Some(item) = opt_item {
-            self.visit_impl_item(item);
-        }
+        walk_list!(self, visit_impl_item, opt_item);
     }
 
     /// Invoked to visit the body of a function, method or closure. Like
@@ -260,9 +261,7 @@
     /// 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 {
-            self.visit_body(body);
-        }
+        walk_list!(self, visit_body, opt_body);
     }
 
     fn visit_param(&mut self, param: &'v Param<'v>) {
@@ -496,21 +495,16 @@
     }
 }
 
-pub fn walk_poly_trait_ref<'v, V>(
+pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
     trait_ref: &'v PolyTraitRef<'v>,
     _modifier: TraitBoundModifier,
-) where
-    V: Visitor<'v>,
-{
+) {
     walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
     visitor.visit_trait_ref(&trait_ref.trait_ref);
 }
 
-pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef<'v>)
-where
-    V: Visitor<'v>,
-{
+pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
     visitor.visit_id(trait_ref.hir_ref_id);
     visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
 }
@@ -572,12 +566,21 @@
             // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
             visitor.visit_enum_def(enum_definition, generics, item.hir_id, item.span)
         }
-        ItemKind::Impl(.., ref generics, ref opt_trait_reference, ref typ, impl_item_refs) => {
+        ItemKind::Impl {
+            unsafety: _,
+            defaultness: _,
+            polarity: _,
+            constness: _,
+            ref generics,
+            ref of_trait,
+            ref self_ty,
+            items,
+        } => {
             visitor.visit_id(item.hir_id);
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
-            visitor.visit_ty(typ);
-            walk_list!(visitor, visit_impl_item_ref, impl_item_refs);
+            walk_list!(visitor, visit_trait_ref, of_trait);
+            visitor.visit_ty(self_ty);
+            walk_list!(visitor, visit_impl_item_ref, items);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
@@ -688,9 +691,7 @@
 ) {
     match *qpath {
         QPath::Resolved(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(qself);
-            }
+            walk_list!(visitor, visit_ty, maybe_qself);
             visitor.visit_path(path, id)
         }
         QPath::TypeRelative(ref qself, ref segment) => {
@@ -712,9 +713,7 @@
     segment: &'v PathSegment<'v>,
 ) {
     visitor.visit_ident(segment.ident);
-    if let Some(id) = segment.hir_id {
-        visitor.visit_id(id);
-    }
+    walk_list!(visitor, visit_id, segment.hir_id);
     if let Some(ref args) = segment.args {
         visitor.visit_generic_args(path_span, args);
     }
@@ -776,8 +775,8 @@
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound)
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
@@ -1003,9 +1002,7 @@
     visitor: &mut V,
     struct_definition: &'v VariantData<'v>,
 ) {
-    if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() {
-        visitor.visit_id(ctor_hir_id);
-    }
+    walk_list!(visitor, visit_id, struct_definition.ctor_hir_id());
     walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
@@ -1125,15 +1122,11 @@
             visitor.visit_qpath(qpath, expression.hir_id, expression.span);
         }
         ExprKind::Break(ref destination, ref opt_expr) => {
-            if let Some(ref label) = destination.label {
-                visitor.visit_label(label);
-            }
+            walk_list!(visitor, visit_label, &destination.label);
             walk_list!(visitor, visit_expr, opt_expr);
         }
         ExprKind::Continue(ref destination) => {
-            if let Some(ref label) = destination.label {
-                visitor.visit_label(label);
-            }
+            walk_list!(visitor, visit_label, &destination.label);
         }
         ExprKind::Ret(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs
index 8bf2e62..f54fa29 100644
--- a/src/librustc_hir/lib.rs
+++ b/src/librustc_hir/lib.rs
@@ -3,7 +3,7 @@
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
 
 #![feature(crate_visibility_modifier)]
-#![feature(const_fn)]
+#![feature(const_fn)] // For the unsizing cast on `&[]`
 #![feature(in_band_lifetimes)]
 #![feature(specialization)]
 #![recursion_limit = "256"]
@@ -15,6 +15,7 @@
 pub mod def_id;
 mod hir;
 pub mod hir_id;
+pub mod intravisit;
 pub mod itemlikevisit;
 pub mod pat_util;
 pub mod print;
diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index 571bab2..b9598c9 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -627,15 +627,16 @@
                 self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, item.ident.name, item.span, true);
             }
-            hir::ItemKind::Impl(
+            hir::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
+                constness,
                 ref generics,
-                ref opt_trait,
-                ref ty,
-                impl_items,
-            ) => {
+                ref of_trait,
+                ref self_ty,
+                items,
+            } => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
@@ -647,23 +648,27 @@
                     self.s.space();
                 }
 
+                if constness == ast::Constness::Const {
+                    self.word_nbsp("const");
+                }
+
                 if let hir::ImplPolarity::Negative = polarity {
                     self.s.word("!");
                 }
 
-                if let Some(ref t) = opt_trait {
+                if let Some(ref t) = of_trait {
                     self.print_trait_ref(t);
                     self.s.space();
                     self.word_space("for");
                 }
 
-                self.print_type(&ty);
+                self.print_type(&self_ty);
                 self.print_where_clause(&generics.where_clause);
 
                 self.s.space();
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
-                for impl_item in impl_items {
+                for impl_item in items {
                     self.ann.nested(self, Nested::ImplItem(impl_item.id));
                 }
                 self.bclose(item.span);
@@ -1767,13 +1772,17 @@
             }
             PatKind::Lit(ref e) => self.print_expr(&e),
             PatKind::Range(ref begin, ref end, ref end_kind) => {
-                self.print_expr(&begin);
-                self.s.space();
+                if let Some(expr) = begin {
+                    self.print_expr(expr);
+                    self.s.space();
+                }
                 match *end_kind {
                     RangeEnd::Included => self.s.word("..."),
                     RangeEnd::Excluded => self.s.word(".."),
                 }
-                self.print_expr(&end);
+                if let Some(expr) = end {
+                    self.print_expr(expr);
+                }
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
                 self.s.word("[");
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 6454784..9490128 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -36,12 +36,13 @@
 use graphviz as dot;
 use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter};
 use rustc::dep_graph::{DepGraphQuery, DepKind, DepNode};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
@@ -159,7 +160,9 @@
 }
 
 impl Visitor<'tcx> for IfThisChanged<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 40dd4c8..c5e7486 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -14,12 +14,13 @@
 //! the required condition is not met.
 
 use rustc::dep_graph::{label_strs, DepNode};
-use rustc::hir::intravisit;
+use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Node as HirNode;
 use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
@@ -314,7 +315,7 @@
                     //HirItem::Trait(..) => ("ItemTrait", LABELS_TRAIT),
 
                     // An implementation, eg `impl<A> Trait for Foo { .. }`
-                    HirItem::Impl(..) => ("ItemKind::Impl", LABELS_IMPL),
+                    HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),
 
                     _ => self.tcx.sess.span_fatal(
                         attr.span,
@@ -547,7 +548,9 @@
 }
 
 impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index adf8f57..ba20006 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -190,6 +190,8 @@
         return;
     }
 
+    let _timer = sess.timer("incr_comp_prepare_session_directory");
+
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
@@ -306,6 +308,8 @@
         return;
     }
 
+    let _timer = sess.timer("incr_comp_finalize_session_directory");
+
     let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
 
     if sess.has_errors_or_delayed_span_bugs() {
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index cb06dae..6c57f79 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -102,6 +102,8 @@
         return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() });
     }
 
+    let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
+
     // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
     // Fortunately, we just checked that this isn't the case.
     let path = dep_graph_path_from(&sess.incr_comp_session_dir());
@@ -159,7 +161,7 @@
     }
 
     MaybeAsync::Async(std::thread::spawn(move || {
-        let _prof_timer = prof.generic_pass("background load prev dep-graph");
+        let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
 
         match load_data(report_incremental_info, &path) {
             LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 9487f02..87f39de 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -32,15 +32,15 @@
         join(
             move || {
                 if tcx.sess.opts.debugging_opts.incremental_queries {
-                    sess.time("persist query result cache", || {
+                    sess.time("incr_comp_persist_result_cache", || {
                         save_in(sess, query_cache_path, |e| encode_query_cache(tcx, e));
                     });
                 }
             },
             || {
-                sess.time("persist dep-graph", || {
+                sess.time("incr_comp_persist_dep_graph", || {
                     save_in(sess, dep_graph_path, |e| {
-                        sess.time("encode dep-graph", || encode_dep_graph(tcx, e))
+                        sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e))
                     });
                 });
             },
@@ -142,7 +142,8 @@
     tcx.sess.opts.dep_tracking_hash().encode(encoder).unwrap();
 
     // Encode the graph data.
-    let serialized_graph = tcx.sess.time("getting serialized graph", || tcx.dep_graph.serialize());
+    let serialized_graph =
+        tcx.sess.time("incr_comp_serialize_dep_graph", || tcx.dep_graph.serialize());
 
     if tcx.sess.opts.debugging_opts.incremental_info {
         #[derive(Clone)]
@@ -223,7 +224,7 @@
         println!("[incremental]");
     }
 
-    tcx.sess.time("encoding serialized graph", || {
+    tcx.sess.time("incr_comp_encode_serialized_dep_graph", || {
         serialized_graph.encode(encoder).unwrap();
     });
 }
@@ -235,7 +236,7 @@
     let serialized_products: Vec<_> = work_products
         .iter()
         .map(|(id, work_product)| SerializedWorkProduct {
-            id: id.clone(),
+            id: *id,
             work_product: work_product.clone(),
         })
         .collect();
@@ -244,7 +245,7 @@
 }
 
 fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut Encoder) {
-    tcx.sess.time("serialize query result cache", || {
+    tcx.sess.time("incr_comp_serialize_result_cache", || {
         tcx.serialize_query_result_cache(encoder).unwrap();
     })
 }
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index be60b75..1fe5248 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -17,10 +17,12 @@
 rustc_builtin_macros = { path = "../librustc_builtin_macros" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc = { path = "../librustc" }
 rustc_ast_lowering = { path = "../librustc_ast_lowering" }
+rustc_ast_passes = { path = "../librustc_ast_passes" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_traits = { path = "../librustc_traits" }
 rustc_data_structures = { path = "../librustc_data_structures" }
@@ -30,6 +32,7 @@
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
+rustc_mir_build = { path = "../librustc_mir_build" }
 rustc_passes = { path = "../librustc_passes" }
 rustc_typeck = { path = "../librustc_typeck" }
 rustc_lint = { path = "../librustc_lint" }
@@ -37,9 +40,13 @@
 rustc_plugin_impl = { path = "../librustc_plugin_impl" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
+rustc_ty = { path = "../librustc_ty" }
 tempfile = "3.0.5"
 once_cell = "1"
 
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["libloaderapi"] }
+
 [dev-dependencies]
 rustc_target = { path = "../librustc_target" }
 
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index c444994..9cd9eb6 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -12,6 +12,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::OnDrop;
 use rustc_errors::registry::Registry;
+use rustc_lint::LintStore;
 use rustc_parse::new_parser_from_source_str;
 use rustc_span::edition;
 use rustc_span::source_map::{FileLoader, FileName, SourceMap};
@@ -36,7 +37,7 @@
     pub(crate) output_dir: Option<PathBuf>,
     pub(crate) output_file: Option<PathBuf>,
     pub(crate) crate_name: Option<String>,
-    pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
+    pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
     pub(crate) override_queries:
         Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>,
 }
@@ -136,7 +137,7 @@
     ///
     /// Note that if you find a Some here you probably want to call that function in the new
     /// function being registered.
-    pub register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
+    pub register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
 
     /// This is a callback from the driver that is called just after we have populated
     /// the list of queries.
@@ -177,11 +178,17 @@
         override_queries: config.override_queries,
     };
 
-    let _sess_abort_error = OnDrop(|| {
-        compiler.sess.diagnostic().print_error_count(registry);
-    });
+    let r = {
+        let _sess_abort_error = OnDrop(|| {
+            compiler.sess.diagnostic().print_error_count(registry);
+        });
 
-    f(&compiler)
+        f(&compiler)
+    };
+
+    let prof = compiler.sess.prof.clone();
+    prof.generic_activity("drop_compiler").run(move || drop(compiler));
+    r
 }
 
 pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 432f79b..d62c753 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -15,7 +15,7 @@
 use rustc::session::Session;
 use rustc::traits;
 use rustc::ty::steal::Steal;
-use rustc::ty::{self, AllArenas, GlobalCtxt, ResolverOutputs, TyCtxt};
+use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_builtin_macros;
 use rustc_codegen_ssa::back::link::emit_metadata;
@@ -27,9 +27,11 @@
 use rustc_expand::base::ExtCtxt;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental;
+use rustc_lint::LintStore;
 use rustc_mir as mir;
+use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
-use rustc_passes::{self, ast_validation, hir_stats, layout_test};
+use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
 use rustc_privacy;
 use rustc_resolve::{Resolver, ResolverArenas};
@@ -37,7 +39,6 @@
 use rustc_span::FileName;
 use rustc_traits;
 use rustc_typeck as typeck;
-use syntax::early_buffered_lints::BufferedEarlyLint;
 use syntax::mut_visit::MutVisitor;
 use syntax::util::node_count::NodeCounter;
 use syntax::{self, ast, visit};
@@ -54,16 +55,13 @@
 use std::{env, fs, iter, mem};
 
 pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
-    sess.diagnostic().set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error);
-    let krate = sess.time("parsing", || match input {
+    let krate = sess.time("parse_crate", || match input {
         Input::File(file) => parse_crate_from_file(file, &sess.parse_sess),
         Input::Str { input, name } => {
             parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess)
         }
     })?;
 
-    sess.diagnostic().set_continue_after_error(true);
-
     if sess.opts.debugging_opts.ast_json_noexpand {
         println!("{}", json::as_json(&krate));
     }
@@ -74,7 +72,7 @@
     }
 
     if let Some(ref s) = sess.opts.debugging_opts.show_span {
-        syntax::show_span::run(sess.diagnostic(), s, &krate);
+        rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate);
     }
 
     if sess.opts.debugging_opts.hir_stats {
@@ -104,7 +102,7 @@
 /// Returns `None` if we're aborting after handling -W help.
 pub fn configure_and_expand(
     sess: Lrc<Session>,
-    lint_store: Lrc<lint::LintStore>,
+    lint_store: Lrc<LintStore>,
     metadata_loader: Box<MetadataLoaderDyn>,
     krate: ast::Crate,
     crate_name: &str,
@@ -154,11 +152,11 @@
 pub fn register_plugins<'a>(
     sess: &'a Session,
     metadata_loader: &'a dyn MetadataLoader,
-    register_lints: impl Fn(&Session, &mut lint::LintStore),
+    register_lints: impl Fn(&Session, &mut LintStore),
     mut krate: ast::Crate,
     crate_name: &str,
-) -> Result<(ast::Crate, Lrc<lint::LintStore>)> {
-    krate = sess.time("attributes injection", || {
+) -> Result<(ast::Crate, Lrc<LintStore>)> {
+    krate = sess.time("attributes_injection", || {
         rustc_builtin_macros::cmdline_attrs::inject(
             krate,
             &sess.parse_sess,
@@ -183,9 +181,7 @@
     rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
 
     if sess.opts.incremental.is_some() {
-        sess.time("garbage-collect incremental cache directory", || {
-            let _prof_timer =
-                sess.prof.generic_activity("incr_comp_garbage_collect_session_directories");
+        sess.time("incr_comp_garbage_collect_session_directories", || {
             if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
                 warn!(
                     "Error while trying to garbage collect incremental \
@@ -196,7 +192,7 @@
         });
     }
 
-    sess.time("recursion limit", || {
+    sess.time("recursion_limit", || {
         middle::recursion_limit::update_limits(sess, &krate);
     });
 
@@ -207,8 +203,8 @@
     register_lints(&sess, &mut lint_store);
 
     let registrars =
-        sess.time("plugin loading", || plugin::load::load_plugins(sess, metadata_loader, &krate));
-    sess.time("plugin registration", || {
+        sess.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate));
+    sess.time("plugin_registration", || {
         let mut registry = plugin::Registry { lint_store: &mut lint_store };
         for registrar in registrars {
             registrar(&mut registry);
@@ -220,13 +216,13 @@
 
 fn configure_and_expand_inner<'a>(
     sess: &'a Session,
-    lint_store: &'a lint::LintStore,
+    lint_store: &'a LintStore,
     mut krate: ast::Crate,
     crate_name: &str,
     resolver_arenas: &'a ResolverArenas<'a>,
     metadata_loader: &'a MetadataLoaderDyn,
 ) -> Result<(ast::Crate, Resolver<'a>)> {
-    sess.time("pre-AST-expansion lint checks", || {
+    sess.time("pre_AST_expansion_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
             lint_store,
@@ -240,7 +236,7 @@
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
     rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition());
 
-    krate = sess.time("crate injection", || {
+    krate = sess.time("crate_injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
         let (krate, name) = rustc_builtin_macros::standard_library_imports::inject(
             krate,
@@ -257,7 +253,7 @@
     util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer());
 
     // Expand all macros
-    krate = sess.time("expansion", || {
+    krate = sess.time("macro_expand_crate", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
         // dependencies. It's up to us to tell the system where to find all the
         // dependent dlls. Note that this uses cfg!(windows) as opposed to
@@ -302,11 +298,11 @@
         let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
 
         // Expand macros now!
-        let krate = sess.time("expand crate", || ecx.monotonic_expander().expand_crate(krate));
+        let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
 
         // The rest is error reporting
 
-        sess.time("check unused macros", || {
+        sess.time("check_unused_macros", || {
             ecx.check_unused_macros();
         });
 
@@ -325,7 +321,7 @@
         krate
     });
 
-    sess.time("maybe building test harness", || {
+    sess.time("maybe_building_test_harness", || {
         rustc_builtin_macros::test_harness::inject(
             &sess.parse_sess,
             &mut resolver,
@@ -349,8 +345,8 @@
         util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
     }
 
-    let has_proc_macro_decls = sess.time("AST validation", || {
-        ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
+    let has_proc_macro_decls = sess.time("AST_validation", || {
+        rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
     });
 
     let crate_types = sess.crate_types.borrow();
@@ -371,7 +367,7 @@
         msg.warn("The generated documentation may be incorrect");
         msg.emit()
     } else {
-        krate = sess.time("maybe creating a macro crate", || {
+        krate = sess.time("maybe_create_a_macro_crate", || {
             let num_crate_types = crate_types.len();
             let is_test_crate = sess.opts.test;
             rustc_builtin_macros::proc_macro_harness::inject(
@@ -401,13 +397,11 @@
         println!("{}", json::as_json(&krate));
     }
 
-    sess.time("name resolution", || {
-        resolver.resolve_crate(&krate);
-    });
+    resolver.resolve_crate(&krate);
 
     // Needs to go *after* expansion to be able to check the results of macro expansion.
-    sess.time("complete gated feature checking", || {
-        syntax::feature_gate::check_crate(
+    sess.time("complete_gated_feature_checking", || {
+        rustc_ast_passes::feature_gate::check_crate(
             &krate,
             &sess.parse_sess,
             &sess.features_untracked(),
@@ -418,8 +412,8 @@
     // Add all buffered lints from the `ParseSess` to the `Session`.
     sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
         info!("{} parse sess buffered_lints", buffered_lints.len());
-        for BufferedEarlyLint { id, span, msg, lint_id } in buffered_lints.drain(..) {
-            resolver.lint_buffer().buffer_lint(lint_id, id, span, &msg);
+        for early_lint in buffered_lints.drain(..) {
+            resolver.lint_buffer().add_early_lint(early_lint);
         }
     });
 
@@ -428,31 +422,29 @@
 
 pub fn lower_to_hir<'res, 'tcx>(
     sess: &'tcx Session,
-    lint_store: &lint::LintStore,
+    lint_store: &LintStore,
     resolver: &'res mut Resolver<'_>,
     dep_graph: &'res DepGraph,
     krate: &'res ast::Crate,
     arena: &'tcx Arena<'tcx>,
 ) -> Result<map::Forest<'tcx>> {
     // Lower AST to HIR.
-    let hir_forest = sess.time("lowering AST -> HIR", || {
-        let hir_crate = rustc_ast_lowering::lower_crate(
-            sess,
-            &dep_graph,
-            &krate,
-            resolver,
-            rustc_parse::nt_to_tokenstream,
-            arena,
-        );
+    let hir_crate = rustc_ast_lowering::lower_crate(
+        sess,
+        &dep_graph,
+        &krate,
+        resolver,
+        rustc_parse::nt_to_tokenstream,
+        arena,
+    );
 
-        if sess.opts.debugging_opts.hir_stats {
-            hir_stats::print_hir_stats(&hir_crate);
-        }
+    if sess.opts.debugging_opts.hir_stats {
+        hir_stats::print_hir_stats(&hir_crate);
+    }
 
-        map::Forest::new(hir_crate, &dep_graph)
-    });
+    let hir_forest = map::Forest::new(hir_crate, &dep_graph);
 
-    sess.time("early lint checks", || {
+    sess.time("early_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
             lint_store,
@@ -620,6 +612,8 @@
     boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
     crate_name: &str,
 ) -> Result<OutputFilenames> {
+    let _timer = sess.timer("prepare_outputs");
+
     // FIXME: rustdoc passes &[] instead of &krate.attrs here
     let outputs = util::build_output_filenames(
         &compiler.input,
@@ -678,6 +672,7 @@
     plugin::build::provide(providers);
     rustc::hir::provide(providers);
     mir::provide(providers);
+    mir_build::provide(providers);
     rustc_privacy::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
@@ -685,6 +680,7 @@
     rustc_passes::provide(providers);
     rustc_resolve::provide(providers);
     rustc_traits::provide(providers);
+    rustc_ty::provide(providers);
     rustc_metadata::provide(providers);
     rustc_lint::provide(providers);
     rustc_codegen_utils::provide(providers);
@@ -713,25 +709,21 @@
 
 pub fn create_global_ctxt<'tcx>(
     compiler: &'tcx Compiler,
-    lint_store: Lrc<lint::LintStore>,
+    lint_store: Lrc<LintStore>,
     hir_forest: &'tcx map::Forest<'tcx>,
     mut resolver_outputs: ResolverOutputs,
     outputs: OutputFilenames,
     crate_name: &str,
     global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
-    all_arenas: &'tcx AllArenas,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
 ) -> QueryContext<'tcx> {
     let sess = &compiler.session();
     let defs = mem::take(&mut resolver_outputs.definitions);
 
     // Construct the HIR map.
-    let hir_map = sess.time("indexing HIR", || {
-        map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs)
-    });
+    let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs);
 
-    let query_result_on_disk_cache =
-        sess.time("load query result cache", || rustc_incremental::load_query_result_cache(sess));
+    let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
 
     let codegen_backend = compiler.codegen_backend();
     let mut local_providers = ty::query::Providers::default();
@@ -746,25 +738,26 @@
         callback(sess, &mut local_providers, &mut extern_providers);
     }
 
-    let gcx = global_ctxt.init_locking(|| {
-        TyCtxt::create_global_ctxt(
-            sess,
-            lint_store,
-            local_providers,
-            extern_providers,
-            &all_arenas,
-            arena,
-            resolver_outputs,
-            hir_map,
-            query_result_on_disk_cache,
-            &crate_name,
-            &outputs,
-        )
+    let gcx = sess.time("setup_global_ctxt", || {
+        global_ctxt.init_locking(|| {
+            TyCtxt::create_global_ctxt(
+                sess,
+                lint_store,
+                local_providers,
+                extern_providers,
+                arena,
+                resolver_outputs,
+                hir_map,
+                query_result_on_disk_cache,
+                &crate_name,
+                &outputs,
+            )
+        })
     });
 
     // Do some initialization of the DepGraph that can only be done with the tcx available.
     ty::tls::enter_global(&gcx, |tcx| {
-        tcx.sess.time("dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
+        tcx.sess.time("dep_graph_tcx_init", || rustc_incremental::dep_graph_tcx_init(tcx));
     });
 
     QueryContext(gcx)
@@ -778,17 +771,17 @@
     let sess = tcx.sess;
     let mut entry_point = None;
 
-    sess.time("misc checking 1", || {
+    sess.time("misc_checking_1", || {
         parallel!(
             {
                 entry_point = sess
-                    .time("looking for entry point", || rustc_passes::entry::find_entry_point(tcx));
+                    .time("looking_for_entry_point", || rustc_passes::entry::find_entry_point(tcx));
 
-                sess.time("looking for plugin registrar", || {
+                sess.time("looking_for_plugin_registrar", || {
                     plugin::build::find_plugin_registrar(tcx)
                 });
 
-                sess.time("looking for derive registrar", || proc_macro_decls::find(tcx));
+                sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
             },
             {
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
@@ -805,17 +798,17 @@
     // passes are timed inside typeck
     typeck::check_crate(tcx)?;
 
-    sess.time("misc checking 2", || {
+    sess.time("misc_checking_2", || {
         parallel!(
             {
-                sess.time("match checking", || {
+                sess.time("match_checking", || {
                     tcx.par_body_owners(|def_id| {
                         tcx.ensure().check_match(def_id);
                     });
                 });
             },
             {
-                sess.time("liveness checking + intrinsic checking", || {
+                sess.time("liveness_and_intrinsic_checking", || {
                     par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
                         // this must run before MIR dump, because
                         // "not all control paths return a value" is reported here.
@@ -831,21 +824,21 @@
         );
     });
 
-    sess.time("MIR borrow checking", || {
+    sess.time("MIR_borrow_checking", || {
         tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id));
     });
 
-    sess.time("dumping Chalk-like clauses", || {
+    sess.time("dumping_chalk_like_clauses", || {
         rustc_traits::lowering::dump_program_clauses(tcx);
     });
 
-    sess.time("MIR effect checking", || {
+    sess.time("MIR_effect_checking", || {
         for def_id in tcx.body_owners() {
             mir::transform::check_unsafety::check_unsafety(tcx, def_id)
         }
     });
 
-    sess.time("layout testing", || layout_test::test_layout(tcx));
+    sess.time("layout_testing", || layout_test::test_layout(tcx));
 
     // Avoid overwhelming user with errors if borrow checking failed.
     // I'm not sure how helpful this is, to be honest, but it avoids a
@@ -856,28 +849,25 @@
         return Err(ErrorReported);
     }
 
-    sess.time("misc checking 3", || {
+    sess.time("misc_checking_3", || {
         parallel!(
             {
-                sess.time("privacy access levels", || {
-                    tcx.ensure().privacy_access_levels(LOCAL_CRATE);
-                });
+                tcx.ensure().privacy_access_levels(LOCAL_CRATE);
+
                 parallel!(
                     {
-                        sess.time("private in public", || {
-                            tcx.ensure().check_private_in_public(LOCAL_CRATE);
-                        });
+                        tcx.ensure().check_private_in_public(LOCAL_CRATE);
                     },
                     {
-                        sess.time("death checking", || rustc_passes::dead::check_crate(tcx));
+                        sess.time("death_checking", || rustc_passes::dead::check_crate(tcx));
                     },
                     {
-                        sess.time("unused lib feature checking", || {
+                        sess.time("unused_lib_feature_checking", || {
                             rustc_passes::stability::check_unused_or_stable_features(tcx)
                         });
                     },
                     {
-                        sess.time("lint checking", || {
+                        sess.time("lint_checking", || {
                             rustc_lint::check_crate(tcx, || {
                                 rustc_lint::BuiltinCombinedLateLintPass::new()
                             });
@@ -886,7 +876,7 @@
                 );
             },
             {
-                sess.time("privacy checking modules", || {
+                sess.time("privacy_checking_modules", || {
                     par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
                         tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
                     });
@@ -929,6 +919,8 @@
         MetadataKind::Uncompressed | MetadataKind::Compressed => tcx.encode_metadata(),
     };
 
+    let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata");
+
     let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
     if need_metadata_file {
         let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str();
@@ -971,10 +963,9 @@
         tcx.print_debug_stats();
     }
 
-    let (metadata, need_metadata_module) =
-        tcx.sess.time("metadata encoding and writing", || encode_and_write_metadata(tcx, outputs));
+    let (metadata, need_metadata_module) = encode_and_write_metadata(tcx, outputs);
 
-    let codegen = tcx.sess.time("codegen", move || {
+    let codegen = tcx.sess.time("codegen_crate", move || {
         codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
     });
 
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 2de0e1e..0af9b17 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -4,17 +4,16 @@
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
 use rustc::hir::map;
-use rustc::lint;
-use rustc::lint::LintStore;
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::session::Session;
 use rustc::ty::steal::Steal;
-use rustc::ty::{AllArenas, GlobalCtxt, ResolverOutputs};
+use rustc::ty::{GlobalCtxt, ResolverOutputs};
 use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_incremental::DepGraphFuture;
+use rustc_lint::LintStore;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::mem;
@@ -67,7 +66,6 @@
     compiler: &'tcx Compiler,
     gcx: Once<GlobalCtxt<'tcx>>,
 
-    all_arenas: AllArenas,
     arena: WorkerLocal<Arena<'tcx>>,
 
     dep_graph_future: Query<Option<DepGraphFuture>>,
@@ -87,7 +85,6 @@
         Queries {
             compiler,
             gcx: Once::new(),
-            all_arenas: AllArenas::new(),
             arena: WorkerLocal::new(|_| Arena::default()),
             dep_graph_future: Default::default(),
             parse: Default::default(),
@@ -133,7 +130,7 @@
             let crate_name = self.crate_name()?.peek().clone();
             let krate = self.parse()?.take();
 
-            let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
+            let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
             let result = passes::register_plugins(
                 self.session(),
                 &*self.codegen_backend().metadata_loader(),
@@ -176,6 +173,7 @@
         self.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let (krate, lint_store) = self.register_plugins()?.take();
+            let _timer = self.session().timer("configure_and_expand");
             passes::configure_and_expand(
                 self.session().clone(),
                 lint_store.clone(),
@@ -195,7 +193,7 @@
                 None => DepGraph::new_disabled(),
                 Some(future) => {
                     let (prev_graph, prev_work_products) =
-                        self.session().time("blocked while dep-graph loading finishes", || {
+                        self.session().time("blocked_on_dep_graph_loading", || {
                             future
                                 .open()
                                 .unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
@@ -256,6 +254,7 @@
             let lint_store = self.expansion()?.peek().2.clone();
             let hir = self.lower_to_hir()?.peek();
             let (ref hir_forest, ref resolver_outputs) = &*hir;
+            let _timer = self.session().timer("create_global_ctxt");
             Ok(passes::create_global_ctxt(
                 self.compiler,
                 lint_store,
@@ -264,7 +263,6 @@
                 outputs,
                 &crate_name,
                 &self.gcx,
-                &self.all_arenas,
                 &self.arena,
             ))
         })
@@ -312,14 +310,19 @@
 
 impl Linker {
     pub fn link(self) -> Result<()> {
-        self.codegen_backend
+        let r = self
+            .codegen_backend
             .join_codegen_and_link(
                 self.ongoing_codegen,
                 &self.sess,
                 &self.dep_graph,
                 &self.prepare_outputs,
             )
-            .map_err(|_| ErrorReported)
+            .map_err(|_| ErrorReported);
+        let prof = self.sess.prof.clone();
+        let dep_graph = self.dep_graph;
+        prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph));
+        r
     }
 }
 
@@ -328,6 +331,7 @@
     where
         F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T,
     {
+        let mut _timer = None;
         let queries = Queries::new(&self);
         let ret = f(&queries);
 
@@ -337,6 +341,8 @@
             }
         }
 
+        _timer = Some(self.session().timer("free_global_ctxt"));
+
         ret
     }
 
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 25ab765..ec75a1c 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -2,7 +2,7 @@
 
 use crate::interface::parse_cfgspecs;
 
-use rustc::lint;
+use rustc::lint::Level;
 use rustc::middle::cstore;
 use rustc::session::config::{build_configuration, build_session_options, to_crate_config};
 use rustc::session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
@@ -186,24 +186,24 @@
     let mut v3 = Options::default();
 
     v1.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("c"), lint::Deny),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("c"), Level::Deny),
+        (String::from("d"), Level::Forbid),
     ];
 
     v2.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("X"), lint::Deny),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("X"), Level::Deny),
+        (String::from("d"), Level::Forbid),
     ];
 
     v3.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("c"), lint::Forbid),
-        (String::from("d"), lint::Deny),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("c"), Level::Forbid),
+        (String::from("d"), Level::Deny),
     ];
 
     assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
@@ -222,17 +222,17 @@
     let mut v2 = Options::default();
 
     v1.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("b"), lint::Warn),
-        (String::from("c"), lint::Deny),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("b"), Level::Warn),
+        (String::from("c"), Level::Deny),
+        (String::from("d"), Level::Forbid),
     ];
 
     v2.lint_opts = vec![
-        (String::from("a"), lint::Allow),
-        (String::from("c"), lint::Deny),
-        (String::from("b"), lint::Warn),
-        (String::from("d"), lint::Forbid),
+        (String::from("a"), Level::Allow),
+        (String::from("c"), Level::Deny),
+        (String::from("b"), Level::Warn),
+        (String::from("d"), Level::Forbid),
     ];
 
     assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
@@ -602,10 +602,6 @@
     assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
     opts = reference.clone();
-    opts.debugging_opts.continue_parse_after_error = true;
-    assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
-
-    opts = reference.clone();
     opts.debugging_opts.force_overflow_checks = Some(true);
     assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index c15dc2f..3e65da9 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -1,8 +1,5 @@
 use log::info;
 use rustc::lint;
-use rustc::session::config::{ErrorOutputType, Input, OutputFilenames};
-use rustc::session::CrateDisambiguator;
-use rustc::session::{self, config, early_error, filesearch, DiagnosticOutput, Session};
 use rustc::ty;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -14,6 +11,11 @@
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_resolve::{self, Resolver};
+use rustc_session as session;
+use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::CrateDisambiguator;
+use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
 use rustc_span::symbol::{sym, Symbol};
@@ -71,10 +73,6 @@
         lint_caps,
     );
 
-    sess.prof.register_queries(|profiler| {
-        rustc::ty::query::QueryName::register_with_profiler(&profiler);
-    });
-
     let codegen_backend = get_codegen_backend(&sess);
 
     let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
@@ -342,19 +340,17 @@
     fn current_dll_path() -> Option<PathBuf> {
         use std::ffi::OsString;
         use std::os::windows::prelude::*;
+        use std::ptr;
 
-        extern "system" {
-            fn GetModuleHandleExW(dwFlags: u32, lpModuleName: usize, phModule: *mut usize) -> i32;
-            fn GetModuleFileNameW(hModule: usize, lpFilename: *mut u16, nSize: u32) -> u32;
-        }
-
-        const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 0x00000004;
+        use winapi::um::libloaderapi::{
+            GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+        };
 
         unsafe {
-            let mut module = 0;
+            let mut module = ptr::null_mut();
             let r = GetModuleHandleExW(
                 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
-                current_dll_path as usize,
+                current_dll_path as usize as *mut _,
                 &mut module,
             );
             if r == 0 {
@@ -424,7 +420,7 @@
     CrateDisambiguator::from(hasher.finish::<Fingerprint>())
 }
 
-pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) {
+pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut LintBuffer) {
     // Unconditionally collect crate types from attributes to make them used
     for a in attrs.iter() {
         if a.check_name(sym::crate_type) {
@@ -446,7 +442,7 @@
                             ast::CRATE_NODE_ID,
                             span,
                             "invalid `crate_type` value",
-                            lint::builtin::BuiltinLintDiagnostics::UnknownCrateTypes(
+                            BuiltinLintDiagnostics::UnknownCrateTypes(
                                 span,
                                 "did you mean".to_string(),
                                 format!("\"{}\"", candidate),
@@ -554,13 +550,13 @@
                 .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
                 .unwrap_or_else(|| input.filestem().to_owned());
 
-            OutputFilenames {
-                out_directory: dirpath,
-                out_filestem: stem,
-                single_output_file: None,
-                extra: sess.opts.cg.extra_filename.clone(),
-                outputs: sess.opts.output_types.clone(),
-            }
+            OutputFilenames::new(
+                dirpath,
+                stem,
+                None,
+                sess.opts.cg.extra_filename.clone(),
+                sess.opts.output_types.clone(),
+            )
         }
 
         Some(ref out_file) => {
@@ -582,18 +578,13 @@
                 sess.warn("ignoring --out-dir flag due to -o flag");
             }
 
-            OutputFilenames {
-                out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
-                out_filestem: out_file
-                    .file_stem()
-                    .unwrap_or_default()
-                    .to_str()
-                    .unwrap()
-                    .to_string(),
-                single_output_file: ofile,
-                extra: sess.opts.cg.extra_filename.clone(),
-                outputs: sess.opts.output_types.clone(),
-            }
+            OutputFilenames::new(
+                out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
+                out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
+                ofile,
+                sess.opts.cg.extra_filename.clone(),
+                sess.opts.output_types.clone(),
+            )
         }
     }
 }
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 820064c..7e23e70 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -12,6 +12,7 @@
 log = "0.4"
 unicode-security = "0.0.2"
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
@@ -19,5 +20,4 @@
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs
index 46202cd..fb11b67 100644
--- a/src/librustc_lint/array_into_iter.rs
+++ b/src/librustc_lint/array_into_iter.rs
@@ -1,10 +1,10 @@
-use crate::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
-use rustc::lint::FutureIncompatibleInfo;
+use crate::{LateContext, LateLintPass, LintContext};
 use rustc::ty;
 use rustc::ty::adjustment::{Adjust, Adjustment};
+use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::symbol::sym;
-use syntax::errors::Applicability;
 
 declare_lint! {
     pub ARRAY_INTO_ITER,
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index c2e20d5..c8d3d5f 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -21,15 +21,12 @@
 //! If you define a new `LateLintPass`, you will also need to add it to the
 //! `late_lint_methods!` invocation in `lib.rs`.
 
-use std::fmt::Write;
-
-use lint::{EarlyContext, EarlyLintPass, LateLintPass, LintPass};
-use lint::{LateContext, LintArray, LintContext};
-use rustc::lint;
-use rustc::lint::FutureIncompatibleInfo;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc::hir::map::Map;
 use rustc::traits::misc::can_type_implement_copy;
 use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::Stability;
 use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
 use rustc_hir as hir;
@@ -37,24 +34,24 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::{GenericParamKind, PatKind};
 use rustc_hir::{HirIdSet, Node};
+use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
 use syntax::ast::{self, Expr};
 use syntax::attr::{self, HasAttrs};
-use syntax::errors::{Applicability, DiagnosticBuilder};
 use syntax::print::pprust::{self, expr_to_string};
-use syntax::ptr::P;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::visit::FnKind;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
 use log::debug;
+use std::fmt::Write;
 
 // hardwired lints from librustc
-pub use lint::builtin::*;
+pub use rustc_session::lint::builtin::*;
 
 declare_lint! {
     WHILE_TRUE,
@@ -254,7 +251,7 @@
                 self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
             }
 
-            ast::ItemKind::Impl(ast::Unsafety::Unsafe, ..) => {
+            ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => {
                 self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait")
             }
 
@@ -434,7 +431,7 @@
                 "a trait"
             }
             hir::ItemKind::TyAlias(..) => "a type alias",
-            hir::ItemKind::Impl(.., Some(ref trait_ref), _, impl_item_refs) => {
+            hir::ItemKind::Impl { of_trait: Some(ref trait_ref), items, .. } => {
                 // If the trait is private, add the impl items to `private_traits` so they don't get
                 // reported for missing docs.
                 let real_trait = trait_ref.path.res.def_id();
@@ -442,7 +439,7 @@
                     match cx.tcx.hir().find(hir_id) {
                         Some(Node::Item(item)) => {
                             if let hir::VisibilityKind::Inherited = item.vis.node {
-                                for impl_item_ref in impl_item_refs {
+                                for impl_item_ref in items {
                                     self.private_traits.insert(impl_item_ref.id.hir_id);
                                 }
                             }
@@ -660,7 +657,7 @@
                                 )
                                 .span_suggestion(
                                     arg.pat.span,
-                                    "Try naming the parameter or explicitly \
+                                    "try naming the parameter or explicitly \
                                     ignoring it",
                                     format!("_: {}", ty_snip),
                                     appl,
@@ -1088,12 +1085,14 @@
         // bound.  Let's see if this type does that.
 
         // We use a HIR visitor to walk the type.
-        use rustc::hir::intravisit::{self, Visitor};
+        use rustc_hir::intravisit::{self, Visitor};
         struct WalkAssocTypes<'a, 'db> {
             err: &'a mut DiagnosticBuilder<'db>,
         }
         impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> {
-            fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
+            type Map = Map<'v>;
+
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1306,11 +1305,13 @@
 
         /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
         /// corresponding to the ellipsis.
-        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P<Expr>, &P<Expr>, Span)> {
+        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> {
             match &pat.kind {
-                PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => {
-                    Some((a, b, *span))
-                }
+                PatKind::Range(
+                    a,
+                    Some(b),
+                    Spanned { span, node: RangeEnd::Included(DotDotDot) },
+                ) => Some((a.as_deref(), b, *span)),
                 _ => None,
             }
         }
@@ -1325,11 +1326,16 @@
             let suggestion = "use `..=` for an inclusive range";
             if parenthesise {
                 self.node_id = Some(pat.id);
+                let end = expr_to_string(&end);
+                let replace = match start {
+                    Some(start) => format!("&({}..={})", expr_to_string(&start), end),
+                    None => format!("&(..={})", end),
+                };
                 let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg);
                 err.span_suggestion(
                     pat.span,
                     suggestion,
-                    format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)),
+                    replace,
                     Applicability::MachineApplicable,
                 );
                 err.emit();
@@ -1806,7 +1812,7 @@
 }
 
 declare_lint_pass!(
-    /// Check for used feature gates in `INCOMPLETE_FEATURES` in `feature_gate.rs`.
+    /// Check for used feature gates in `INCOMPLETE_FEATURES` in `librustc_feature/active.rs`.
     IncompleteFeatures => [INCOMPLETE_FEATURES]
 );
 
@@ -1928,21 +1934,21 @@
             use rustc::ty::TyKind::*;
             match ty.kind {
                 // Primitive types that don't like 0 as a value.
-                Ref(..) => Some((format!("References must be non-null"), None)),
+                Ref(..) => Some((format!("references must be non-null"), None)),
                 Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)),
-                FnPtr(..) => Some((format!("Function pointers must be non-null"), None)),
-                Never => Some((format!("The never type (`!`) has no valid value"), None)),
+                FnPtr(..) => Some((format!("function pointers must be non-null"), None)),
+                Never => Some((format!("the `!` type has no valid value"), None)),
                 RawPtr(tm) if matches!(tm.ty.kind, Dynamic(..)) =>
                 // raw ptr to dyn Trait
                 {
-                    Some((format!("The vtable of a wide raw pointer must be non-null"), None))
+                    Some((format!("the vtable of a wide raw pointer must be non-null"), None))
                 }
                 // Primitive types with other constraints.
                 Bool if init == InitKind::Uninit => {
-                    Some((format!("Booleans must be `true` or `false`"), None))
+                    Some((format!("booleans must be either `true` or `false`"), None))
                 }
                 Char if init == InitKind::Uninit => {
-                    Some((format!("Characters must be a valid unicode codepoint"), None))
+                    Some((format!("characters must be a valid Unicode codepoint"), None))
                 }
                 // Recurse and checks for some compound types.
                 Adt(adt_def, substs) if !adt_def.is_union() => {
@@ -1953,13 +1959,16 @@
                         // return `Bound::Excluded`.  (And we have tests checking that we
                         // handle the attribute correctly.)
                         (Bound::Included(lo), _) if lo > 0 => {
-                            return Some((format!("{} must be non-null", ty), None));
+                            return Some((format!("`{}` must be non-null", ty), None));
                         }
                         (Bound::Included(_), _) | (_, Bound::Included(_))
                             if init == InitKind::Uninit =>
                         {
                             return Some((
-                                format!("{} must be initialized inside its custom valid range", ty),
+                                format!(
+                                    "`{}` must be initialized inside its custom valid range",
+                                    ty,
+                                ),
                                 None,
                             ));
                         }
@@ -1967,7 +1976,7 @@
                     }
                     // Now, recurse.
                     match adt_def.variants.len() {
-                        0 => Some((format!("0-variant enums have no valid value"), None)),
+                        0 => Some((format!("enums with no variants have no valid value"), None)),
                         1 => {
                             // Struct, or enum with exactly one variant.
                             // Proceed recursively, check all fields.
diff --git a/src/librustc/lint/context.rs b/src/librustc_lint/context.rs
similarity index 85%
rename from src/librustc/lint/context.rs
rename to src/librustc_lint/context.rs
index 0ac6824..3b8cce5 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc_lint/context.rs
@@ -16,26 +16,27 @@
 
 use self::TargetLint::*;
 
-use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
-use crate::lint::builtin::BuiltinLintDiagnostics;
-use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
-use crate::lint::{EarlyLintPassObject, LateLintPassObject};
-use crate::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
-use crate::middle::privacy::AccessLevels;
-use crate::session::Session;
-use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
-use crate::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
-use errors::DiagnosticBuilder;
+use crate::levels::LintLevelsBuilder;
+use crate::passes::{EarlyLintPassObject, LateLintPassObject};
+use rustc::hir::map::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc::lint::add_elided_lifetime_in_path_suggestion;
+use rustc::middle::privacy::AccessLevels;
+use rustc::middle::stability;
+use rustc::ty::layout::{LayoutError, LayoutOf, TyLayout};
+use rustc::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_span::{symbol::Symbol, MultiSpan, Span};
-use std::slice;
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
+use rustc_session::Session;
+use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
+use std::slice;
 
 /// Information about the registered lints.
 ///
@@ -64,17 +65,6 @@
     lint_groups: FxHashMap<&'static str, LintGroup>,
 }
 
-/// Lints that are buffered up early on in the `Session` before the
-/// `LintLevels` is calculated
-#[derive(PartialEq, Debug)]
-pub struct BufferedEarlyLint {
-    pub lint_id: LintId,
-    pub ast_id: ast::NodeId,
-    pub span: MultiSpan,
-    pub msg: String,
-    pub diagnostic: BuiltinLintDiagnostics,
-}
-
 /// The target of the `by_name` map, which accounts for renaming/deprecation.
 enum TargetLint {
     /// A direct lint target
@@ -254,7 +244,7 @@
 
     pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
         let target = match self.by_name.get(new_name) {
-            Some(&Id(lint_id)) => lint_id.clone(),
+            Some(&Id(lint_id)) => lint_id,
             _ => bug!("invalid lint renaming of {} to {}", old_name, new_name),
         };
         self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
@@ -290,7 +280,8 @@
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
             CheckLintNameResult::NoLint(suggestion) => {
-                let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
+                let mut err =
+                    struct_span_err!(sess, DUMMY_SP, E0602, "unknown lint: `{}`", lint_name);
 
                 if let Some(suggestion) = suggestion {
                     err.help(&format!("did you mean: `{}`", suggestion));
@@ -494,7 +485,85 @@
         diagnostic: BuiltinLintDiagnostics,
     ) {
         let mut db = self.lookup(lint, span, msg);
-        diagnostic.run(self.sess(), &mut db);
+
+        let sess = self.sess();
+        match diagnostic {
+            BuiltinLintDiagnostics::Normal => (),
+            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
+                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                    Ok(s) if is_global => {
+                        (format!("dyn ({})", s), Applicability::MachineApplicable)
+                    }
+                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
+                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
+                };
+                db.span_suggestion(span, "use `dyn`", sugg, app);
+            }
+            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
+                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                    Ok(ref s) => {
+                        // FIXME(Manishearth) ideally the emitting code
+                        // can tell us whether or not this is global
+                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
+
+                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
+                    }
+                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
+                };
+                db.span_suggestion(span, "use `crate`", sugg, app);
+            }
+            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
+                db.span_label(
+                    span,
+                    "names from parent modules are not accessible without an explicit import",
+                );
+            }
+            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
+                db.span_note(span_def, "the macro is defined here");
+            }
+            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                n,
+                path_span,
+                incl_angl_brckt,
+                insertion_span,
+                anon_lts,
+            ) => {
+                add_elided_lifetime_in_path_suggestion(
+                    sess,
+                    &mut db,
+                    n,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_span,
+                    anon_lts,
+                );
+            }
+            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
+                db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
+            }
+            BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
+                if !replaces.is_empty() {
+                    db.tool_only_multipart_suggestion(
+                        &message,
+                        replaces,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
+                for (span, is_imported) in spans {
+                    let introduced = if is_imported { "imported" } else { "defined" };
+                    db.span_label(
+                        span,
+                        format!("the item `{}` is already {} here", ident, introduced),
+                    );
+                }
+            }
+            BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
+                stability::deprecation_suggestion(&mut db, suggestion, span)
+            }
+        }
+
         db.emit();
     }
 
@@ -563,7 +632,7 @@
             sess,
             krate,
             lint_store,
-            builder: LintLevelSets::builder(sess, warn_about_weird_lints, lint_store),
+            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store),
             buffered,
         }
     }
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index a099568..490114b 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -14,17 +14,16 @@
 //! upon. As the ast is traversed, this keeps track of the current lint level
 //! for all lint attributes.
 
-use rustc::lint::{EarlyContext, LintStore};
-use rustc::lint::{EarlyLintPass, EarlyLintPassObject};
-use rustc::lint::{LintBuffer, LintContext, LintPass};
-use rustc::session::Session;
-
+use crate::context::{EarlyContext, LintContext, LintStore};
+use crate::passes::{EarlyLintPass, EarlyLintPassObject};
+use rustc_session::lint::{LintBuffer, LintPass};
+use rustc_session::Session;
 use rustc_span::Span;
-use std::slice;
 use syntax::ast;
 use syntax::visit as ast_visit;
 
 use log::debug;
+use std::slice;
 
 macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
@@ -291,7 +290,7 @@
     )
 }
 
-early_lint_methods!(early_lint_pass_impl, []);
+crate::early_lint_methods!(early_lint_pass_impl, []);
 
 fn early_lint_crate<T: EarlyLintPass>(
     sess: &Session,
@@ -350,16 +349,19 @@
         }
     } else {
         for pass in &mut passes {
-            buffered = sess.time(&format!("running lint: {}", pass.name()), || {
-                early_lint_crate(
-                    sess,
-                    lint_store,
-                    krate,
-                    EarlyLintPassObjects { lints: slice::from_mut(pass) },
-                    buffered,
-                    pre_expansion,
-                )
-            });
+            buffered = sess
+                .prof
+                .extra_verbose_generic_activity(&format!("running lint: {}", pass.name()))
+                .run(|| {
+                    early_lint_crate(
+                        sess,
+                        lint_store,
+                        krate,
+                        EarlyLintPassObjects { lints: slice::from_mut(pass) },
+                        buffered,
+                        pre_expansion,
+                    )
+                });
         }
     }
 
diff --git a/src/librustc/lint/internal.rs b/src/librustc_lint/internal.rs
similarity index 93%
rename from src/librustc/lint/internal.rs
rename to src/librustc_lint/internal.rs
index 69f212a..91aeccb 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc_lint/internal.rs
@@ -1,20 +1,19 @@
 //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
 //! Clippy.
 
-use crate::lint::{
-    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
-};
-use errors::Applicability;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
 use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
-use rustc_session::declare_tool_lint;
+use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast::{Ident, Item, ItemKind};
 
 declare_tool_lint! {
     pub rustc::DEFAULT_HASH_TYPES,
     Allow,
-    "forbid HashMap and HashSet and suggest the FxHash* variants"
+    "forbid HashMap and HashSet and suggest the FxHash* variants",
+    report_in_external_macro: true
 }
 
 pub struct DefaultHashTypes {
@@ -54,19 +53,22 @@
 declare_tool_lint! {
     pub rustc::USAGE_OF_TY_TYKIND,
     Allow,
-    "usage of `ty::TyKind` outside of the `ty::sty` module"
+    "usage of `ty::TyKind` outside of the `ty::sty` module",
+    report_in_external_macro: true
 }
 
 declare_tool_lint! {
     pub rustc::TY_PASS_BY_REFERENCE,
     Allow,
-    "passing `Ty` or `TyCtxt` by reference"
+    "passing `Ty` or `TyCtxt` by reference",
+    report_in_external_macro: true
 }
 
 declare_tool_lint! {
     pub rustc::USAGE_OF_QUALIFIED_TY,
     Allow,
-    "using `ty::{Ty,TyCtxt}` instead of importing it"
+    "using `ty::{Ty,TyCtxt}` instead of importing it",
+    report_in_external_macro: true
 }
 
 declare_lint_pass!(TyTyKind => [
@@ -219,7 +221,7 @@
 
 impl EarlyLintPass for LintPassImpl {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.kind {
+        if let ItemKind::Impl { of_trait: Some(lint_pass), .. } = &item.kind {
             if let Some(last) = lint_pass.path.segments.last() {
                 if last.ident.name == sym::LintPass {
                     let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs
index 2e0a201..30a3788 100644
--- a/src/librustc_lint/late.rs
+++ b/src/librustc_lint/late.rs
@@ -14,21 +14,29 @@
 //! upon. As the ast is traversed, this keeps track of the current lint level
 //! for all lint attributes.
 
-use rustc::hir::intravisit as hir_visit;
-use rustc::hir::intravisit::Visitor;
-use rustc::lint::LateContext;
-use rustc::lint::LintPass;
-use rustc::lint::{LateLintPass, LateLintPassObject};
+use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
+use rustc::hir::map::Map;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit as hir_visit;
+use rustc_hir::intravisit::Visitor;
+use rustc_session::lint::LintPass;
 use rustc_span::Span;
-use std::slice;
 use syntax::ast;
+use syntax::walk_list;
 
 use log::debug;
-use syntax::walk_list;
+use std::any::Any;
+use std::slice;
+
+/// Extract the `LintStore` from the query context.
+/// This function exists because we've erased `LintStore` as `dyn Any` in the context.
+crate fn unerased_lint_store<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx LintStore {
+    let store: &dyn Any = &*tcx.lint_store;
+    store.downcast_ref().unwrap()
+}
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
@@ -86,10 +94,12 @@
 impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
     for LateContextAndPass<'a, 'tcx, T>
 {
+    type Map = Map<'tcx>;
+
     /// Because lints are scoped lexically, we want to walk nested
     /// items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, Self::Map> {
         hir_visit::NestedVisitorMap::All(&self.context.tcx.hir())
     }
 
@@ -339,7 +349,7 @@
     )
 }
 
-late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
+crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
 
 fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
     tcx: TyCtxt<'tcx>,
@@ -353,7 +363,7 @@
         tables: &ty::TypeckTables::empty(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
-        lint_store: &tcx.lint_store,
+        lint_store: unerased_lint_store(tcx),
         last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
         generics: None,
         only_module: true,
@@ -383,7 +393,7 @@
     late_lint_mod_pass(tcx, module_def_id, builtin_lints);
 
     let mut passes: Vec<_> =
-        tcx.lint_store.late_module_passes.iter().map(|pass| (pass)()).collect();
+        unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
 
     if !passes.is_empty() {
         late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
@@ -400,7 +410,7 @@
         tables: &ty::TypeckTables::empty(None),
         param_env: ty::ParamEnv::empty(),
         access_levels,
-        lint_store: &tcx.lint_store,
+        lint_store: unerased_lint_store(tcx),
         last_node_with_lint_attrs: hir::CRATE_HIR_ID,
         generics: None,
         only_module: false,
@@ -421,7 +431,7 @@
 }
 
 fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
-    let mut passes = tcx.lint_store.late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
+    let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
 
     if !tcx.sess.opts.debugging_opts.no_interleave_lints {
         if !passes.is_empty() {
@@ -431,18 +441,27 @@
         late_lint_pass_crate(tcx, builtin_lints);
     } else {
         for pass in &mut passes {
-            tcx.sess.time(&format!("running late lint: {}", pass.name()), || {
-                late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
-            });
+            tcx.sess
+                .prof
+                .extra_verbose_generic_activity(&format!("running late lint: {}", pass.name()))
+                .run(|| {
+                    late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
+                });
         }
 
         let mut passes: Vec<_> =
-            tcx.lint_store.late_module_passes.iter().map(|pass| (pass)()).collect();
+            unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
 
         for pass in &mut passes {
-            tcx.sess.time(&format!("running late module lint: {}", pass.name()), || {
-                late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
-            });
+            tcx.sess
+                .prof
+                .extra_verbose_generic_activity(&format!(
+                    "running late module lint: {}",
+                    pass.name()
+                ))
+                .run(|| {
+                    late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
+                });
         }
     }
 }
@@ -454,13 +473,13 @@
 ) {
     join(
         || {
-            tcx.sess.time("crate lints", || {
+            tcx.sess.time("crate_lints", || {
                 // Run whole crate non-incremental lints
                 late_lint_crate(tcx, builtin_lints());
             });
         },
         || {
-            tcx.sess.time("module lints", || {
+            tcx.sess.time("module_lints", || {
                 // Run per-module lints
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
                     tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs
index e060d6b..d5bbdc5 100644
--- a/src/librustc_lint/levels.rs
+++ b/src/librustc_lint/levels.rs
@@ -1,21 +1,32 @@
-use rustc::hir::intravisit;
-use rustc::lint::{LintLevelMap, LintLevelSets, LintLevelsBuilder, LintStore};
+use crate::context::{CheckLintNameResult, LintStore};
+use crate::late::unerased_lint_store;
+use rustc::hir::map::Map;
+use rustc::lint::struct_lint_level;
+use rustc::lint::{LintLevelMap, LintLevelSets, LintSet, LintSource};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_hir::hir_id::HirId;
+use rustc_hir::intravisit;
+use rustc_session::lint::{builtin, Level, Lint};
+use rustc_session::Session;
+use rustc_span::{sym, MultiSpan, Symbol};
 use syntax::ast;
+use syntax::attr;
+use syntax::print::pprust;
+use syntax::sess::feature_err;
+use syntax::unwrap_or;
 
-pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
+use std::cmp;
 
 fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     assert_eq!(cnum, LOCAL_CRATE);
-    let store = &tcx.lint_store;
-    let mut builder = LintLevelMapBuilder {
-        levels: LintLevelSets::builder(tcx.sess, false, &store),
-        tcx: tcx,
-        store: store,
-    };
+    let store = unerased_lint_store(tcx);
+    let levels = LintLevelsBuilder::new(tcx.sess, false, &store);
+    let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
     let push = builder.levels.push(&krate.attrs, &store);
@@ -29,6 +40,378 @@
     tcx.arena.alloc(builder.levels.build_map())
 }
 
+pub struct LintLevelsBuilder<'a> {
+    sess: &'a Session,
+    sets: LintLevelSets,
+    id_to_set: FxHashMap<HirId, u32>,
+    cur: u32,
+    warn_about_weird_lints: bool,
+}
+
+pub struct BuilderPush {
+    prev: u32,
+    pub changed: bool,
+}
+
+impl<'a> LintLevelsBuilder<'a> {
+    pub fn new(sess: &'a Session, warn_about_weird_lints: bool, store: &LintStore) -> Self {
+        let mut builder = LintLevelsBuilder {
+            sess,
+            sets: LintLevelSets::new(),
+            cur: 0,
+            id_to_set: Default::default(),
+            warn_about_weird_lints,
+        };
+        builder.process_command_line(sess, store);
+        assert_eq!(builder.sets.list.len(), 1);
+        builder
+    }
+
+    fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
+        let mut specs = FxHashMap::default();
+        self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
+
+        for &(ref lint_name, level) in &sess.opts.lint_opts {
+            store.check_lint_name_cmdline(sess, &lint_name, level);
+
+            // If the cap is less than this specified level, e.g., if we've got
+            // `--cap-lints allow` but we've also got `-D foo` then we ignore
+            // this specification as the lint cap will set it to allow anyway.
+            let level = cmp::min(level, self.sets.lint_cap);
+
+            let lint_flag_val = Symbol::intern(lint_name);
+            let ids = match store.find_lints(&lint_name) {
+                Ok(ids) => ids,
+                Err(_) => continue, // errors handled in check_lint_name_cmdline above
+            };
+            for id in ids {
+                let src = LintSource::CommandLine(lint_flag_val);
+                specs.insert(id, (level, src));
+            }
+        }
+
+        self.sets.list.push(LintSet::CommandLine { specs });
+    }
+
+    /// Pushes a list of AST lint attributes onto this context.
+    ///
+    /// This function will return a `BuilderPush` object which should be passed
+    /// to `pop` when this scope for the attributes provided is exited.
+    ///
+    /// This function will perform a number of tasks:
+    ///
+    /// * It'll validate all lint-related attributes in `attrs`
+    /// * It'll mark all lint-related attributes as used
+    /// * Lint levels will be updated based on the attributes provided
+    /// * Lint attributes are validated, e.g., a #[forbid] can't be switched to
+    ///   #[allow]
+    ///
+    /// Don't forget to call `pop`!
+    pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush {
+        let mut specs = FxHashMap::default();
+        let sess = self.sess;
+        let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
+        for attr in attrs {
+            let level = match Level::from_symbol(attr.name_or_empty()) {
+                None => continue,
+                Some(lvl) => lvl,
+            };
+
+            let meta = unwrap_or!(attr.meta(), continue);
+            attr::mark_used(attr);
+
+            let mut metas = unwrap_or!(meta.meta_item_list(), continue);
+
+            if metas.is_empty() {
+                // FIXME (#55112): issue unused-attributes lint for `#[level()]`
+                continue;
+            }
+
+            // Before processing the lint names, look for a reason (RFC 2383)
+            // at the end.
+            let mut reason = None;
+            let tail_li = &metas[metas.len() - 1];
+            if let Some(item) = tail_li.meta_item() {
+                match item.kind {
+                    ast::MetaItemKind::Word => {} // actual lint names handled later
+                    ast::MetaItemKind::NameValue(ref name_value) => {
+                        if item.path == sym::reason {
+                            // found reason, reslice meta list to exclude it
+                            metas = &metas[0..metas.len() - 1];
+                            // FIXME (#55112): issue unused-attributes lint if we thereby
+                            // don't have any lint names (`#[level(reason = "foo")]`)
+                            if let ast::LitKind::Str(rationale, _) = name_value.kind {
+                                if !self.sess.features_untracked().lint_reasons {
+                                    feature_err(
+                                        &self.sess.parse_sess,
+                                        sym::lint_reasons,
+                                        item.span,
+                                        "lint reasons are experimental",
+                                    )
+                                    .emit();
+                                }
+                                reason = Some(rationale);
+                            } else {
+                                bad_attr(name_value.span)
+                                    .span_label(name_value.span, "reason must be a string literal")
+                                    .emit();
+                            }
+                        } else {
+                            bad_attr(item.span)
+                                .span_label(item.span, "bad attribute argument")
+                                .emit();
+                        }
+                    }
+                    ast::MetaItemKind::List(_) => {
+                        bad_attr(item.span).span_label(item.span, "bad attribute argument").emit();
+                    }
+                }
+            }
+
+            for li in metas {
+                let meta_item = match li.meta_item() {
+                    Some(meta_item) if meta_item.is_word() => meta_item,
+                    _ => {
+                        let sp = li.span();
+                        let mut err = bad_attr(sp);
+                        let mut add_label = true;
+                        if let Some(item) = li.meta_item() {
+                            if let ast::MetaItemKind::NameValue(_) = item.kind {
+                                if item.path == sym::reason {
+                                    err.span_label(sp, "reason in lint attribute must come last");
+                                    add_label = false;
+                                }
+                            }
+                        }
+                        if add_label {
+                            err.span_label(sp, "bad attribute argument");
+                        }
+                        err.emit();
+                        continue;
+                    }
+                };
+                let tool_name = if meta_item.path.segments.len() > 1 {
+                    let tool_ident = meta_item.path.segments[0].ident;
+                    if !attr::is_known_lint_tool(tool_ident) {
+                        struct_span_err!(
+                            sess,
+                            tool_ident.span,
+                            E0710,
+                            "an unknown tool name found in scoped lint: `{}`",
+                            pprust::path_to_string(&meta_item.path),
+                        )
+                        .emit();
+                        continue;
+                    }
+
+                    Some(tool_ident.name)
+                } else {
+                    None
+                };
+                let name = meta_item.path.segments.last().expect("empty lint name").ident.name;
+                match store.check_lint_name(&name.as_str(), tool_name) {
+                    CheckLintNameResult::Ok(ids) => {
+                        let src = LintSource::Node(name, li.span(), reason);
+                        for id in ids {
+                            specs.insert(*id, (level, src));
+                        }
+                    }
+
+                    CheckLintNameResult::Tool(result) => {
+                        match result {
+                            Ok(ids) => {
+                                let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+                                let src = LintSource::Node(
+                                    Symbol::intern(complete_name),
+                                    li.span(),
+                                    reason,
+                                );
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((Some(ids), new_lint_name)) => {
+                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                                let (lvl, src) =
+                                    self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
+                                let msg = format!(
+                                    "lint name `{}` is deprecated \
+                                     and may not have an effect in the future. \
+                                     Also `cfg_attr(cargo-clippy)` won't be necessary anymore",
+                                    name
+                                );
+                                struct_lint_level(
+                                    self.sess,
+                                    lint,
+                                    lvl,
+                                    src,
+                                    Some(li.span().into()),
+                                    &msg,
+                                )
+                                .span_suggestion(
+                                    li.span(),
+                                    "change it to",
+                                    new_lint_name.to_string(),
+                                    Applicability::MachineApplicable,
+                                )
+                                .emit();
+
+                                let src = LintSource::Node(
+                                    Symbol::intern(&new_lint_name),
+                                    li.span(),
+                                    reason,
+                                );
+                                for id in ids {
+                                    specs.insert(*id, (level, src));
+                                }
+                            }
+                            Err((None, _)) => {
+                                // If Tool(Err(None, _)) is returned, then either the lint does not
+                                // exist in the tool or the code was not compiled with the tool and
+                                // therefore the lint was never added to the `LintStore`. To detect
+                                // this is the responsibility of the lint tool.
+                            }
+                        }
+                    }
+
+                    _ if !self.warn_about_weird_lints => {}
+
+                    CheckLintNameResult::Warning(msg, renamed) => {
+                        let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                        let (level, src) =
+                            self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
+                        let mut err = struct_lint_level(
+                            self.sess,
+                            lint,
+                            level,
+                            src,
+                            Some(li.span().into()),
+                            &msg,
+                        );
+                        if let Some(new_name) = renamed {
+                            err.span_suggestion(
+                                li.span(),
+                                "use the new name",
+                                new_name,
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                        err.emit();
+                    }
+                    CheckLintNameResult::NoLint(suggestion) => {
+                        let lint = builtin::UNKNOWN_LINTS;
+                        let (level, src) =
+                            self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
+                        let msg = format!("unknown lint: `{}`", name);
+                        let mut db = struct_lint_level(
+                            self.sess,
+                            lint,
+                            level,
+                            src,
+                            Some(li.span().into()),
+                            &msg,
+                        );
+
+                        if let Some(suggestion) = suggestion {
+                            db.span_suggestion(
+                                li.span(),
+                                "did you mean",
+                                suggestion.to_string(),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+
+                        db.emit();
+                    }
+                }
+            }
+        }
+
+        for (id, &(level, ref src)) in specs.iter() {
+            if level == Level::Forbid {
+                continue;
+            }
+            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) {
+                (Some(Level::Forbid), src) => src,
+                _ => continue,
+            };
+            let forbidden_lint_name = match forbid_src {
+                LintSource::Default => id.to_string(),
+                LintSource::Node(name, _, _) => name.to_string(),
+                LintSource::CommandLine(name) => name.to_string(),
+            };
+            let (lint_attr_name, lint_attr_span) = match *src {
+                LintSource::Node(name, span, _) => (name, span),
+                _ => continue,
+            };
+            let mut diag_builder = struct_span_err!(
+                self.sess,
+                lint_attr_span,
+                E0453,
+                "{}({}) overruled by outer forbid({})",
+                level.as_str(),
+                lint_attr_name,
+                forbidden_lint_name
+            );
+            diag_builder.span_label(lint_attr_span, "overruled by previous forbid");
+            match forbid_src {
+                LintSource::Default => {}
+                LintSource::Node(_, forbid_source_span, reason) => {
+                    diag_builder.span_label(forbid_source_span, "`forbid` level set here");
+                    if let Some(rationale) = reason {
+                        diag_builder.note(&rationale.as_str());
+                    }
+                }
+                LintSource::CommandLine(_) => {
+                    diag_builder.note("`forbid` lint level was set on command line");
+                }
+            }
+            diag_builder.emit();
+            // don't set a separate error for every lint in the group
+            break;
+        }
+
+        let prev = self.cur;
+        if specs.len() > 0 {
+            self.cur = self.sets.list.len() as u32;
+            self.sets.list.push(LintSet::Node { specs: specs, parent: prev });
+        }
+
+        BuilderPush { prev: prev, changed: prev != self.cur }
+    }
+
+    /// Called after `push` when the scope of a set of attributes are exited.
+    pub fn pop(&mut self, push: BuilderPush) {
+        self.cur = push.prev;
+    }
+
+    /// Used to emit a lint-related diagnostic based on the current state of
+    /// this lint context.
+    pub fn struct_lint(
+        &self,
+        lint: &'static Lint,
+        span: Option<MultiSpan>,
+        msg: &str,
+    ) -> DiagnosticBuilder<'a> {
+        let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess);
+        struct_lint_level(self.sess, lint, level, src, span, msg)
+    }
+
+    /// Registers the ID provided with the current set of lints stored in
+    /// this context.
+    pub fn register_id(&mut self, id: HirId) {
+        self.id_to_set.insert(id, self.cur);
+    }
+
+    pub fn build(self) -> LintLevelSets {
+        self.sets
+    }
+
+    pub fn build_map(self) -> LintLevelMap {
+        LintLevelMap { sets: self.sets, id_to_set: self.id_to_set }
+    }
+}
+
 struct LintLevelMapBuilder<'a, 'tcx> {
     levels: LintLevelsBuilder<'tcx>,
     tcx: TyCtxt<'tcx>,
@@ -50,7 +433,9 @@
 }
 
 impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index e272c3a..78e9d0f 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -1,9 +1,25 @@
-//! # Lints in the Rust compiler
+//! Lints, aka compiler warnings.
 //!
-//! This currently only contains the definitions and implementations
-//! of most of the lints that `rustc` supports directly, it does not
-//! contain the infrastructure for defining/registering lints. That is
-//! available in `rustc::lint` and `rustc_driver::plugin` respectively.
+//! A 'lint' check is a kind of miscellaneous constraint that a user _might_
+//! want to enforce, but might reasonably want to permit as well, on a
+//! module-by-module basis. They contrast with static constraints enforced by
+//! other phases of the compiler, which are generally required to hold in order
+//! to compile the program at all.
+//!
+//! Most lints can be written as `LintPass` instances. These run after
+//! all other analyses. The `LintPass`es built into rustc are defined
+//! within `rustc_session::lint::builtin`,
+//! which has further comments on how to add such a lint.
+//! rustc can also load user-defined lint plugins via the plugin mechanism.
+//!
+//! Some of rustc's lints are defined elsewhere in the compiler and work by
+//! calling `add_lint()` on the overall `Session` object. This works when
+//! it happens before the main lint pass, which emits the lints stored by
+//! `add_lint()`. To emit lints after the main lint pass (from codegen, for
+//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
+//! in `context.rs`.
+//!
+//! Some code also exists in `rustc_session::lint`, `rustc::lint`.
 //!
 //! ## Note
 //!
@@ -14,6 +30,8 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
+#![feature(never_type)]
 #![feature(nll)]
 #![recursion_limit = "256"]
 
@@ -24,44 +42,47 @@
 
 mod array_into_iter;
 pub mod builtin;
+mod context;
 mod early;
+mod internal;
 mod late;
 mod levels;
 mod non_ascii_idents;
 mod nonstandard_style;
+mod passes;
 mod redundant_semicolon;
 mod types;
 mod unused;
 
-use rustc::lint;
-use rustc::lint::builtin::{
-    BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
-    INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS,
-};
-use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-
+use rustc_session::lint::builtin::{
+    BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
+    INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS,
+};
 use rustc_span::Span;
 use syntax::ast;
 
-use lint::LintId;
-
 use array_into_iter::ArrayIntoIter;
 use builtin::*;
+use internal::*;
 use non_ascii_idents::*;
 use nonstandard_style::*;
 use redundant_semicolon::*;
-use rustc::lint::internal::*;
 use types::*;
 use unused::*;
 
-/// Useful for other parts of the compiler.
+/// Useful for other parts of the compiler / Clippy.
 pub use builtin::SoftLints;
+pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore};
 pub use early::check_ast_crate;
 pub use late::check_crate;
+pub use passes::{EarlyLintPass, LateLintPass};
+pub use rustc_session::lint::Level::{self, *};
+pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
+pub use rustc_session::lint::{LintArray, LintPass};
 
 pub fn provide(providers: &mut Providers<'_>) {
     levels::provide(providers);
@@ -178,8 +199,8 @@
 
 late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]);
 
-pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> lint::LintStore {
-    let mut lint_store = lint::LintStore::new();
+pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintStore {
+    let mut lint_store = LintStore::new();
 
     register_builtins(&mut lint_store, no_interleave_lints);
     if internal_lints {
@@ -192,7 +213,7 @@
 /// Tell the `LintStore` about all the built-in lints (the ones
 /// defined in this crate and the ones defined in
 /// `rustc::lint::builtin`).
-fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) {
+fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
     macro_rules! add_lint_group {
         ($name:expr, $($lint:ident),*) => (
             store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]);
@@ -389,7 +410,7 @@
     store.register_removed("plugin_as_library", "plugins have been deprecated and retired");
 }
 
-fn register_internals(store: &mut lint::LintStore) {
+fn register_internals(store: &mut LintStore) {
     store.register_lints(&DefaultHashTypes::get_lints());
     store.register_early_pass(|| box DefaultHashTypes::new());
     store.register_lints(&LintPassImpl::get_lints());
diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs
index f30d0bc..3c85a1b 100644
--- a/src/librustc_lint/non_ascii_idents.rs
+++ b/src/librustc_lint/non_ascii_idents.rs
@@ -1,4 +1,4 @@
-use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
 use syntax::ast;
 
 declare_lint! {
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index d50c048..394da4a 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -1,17 +1,15 @@
-use lint::{EarlyContext, LateContext, LintArray, LintContext};
-use lint::{EarlyLintPass, LateLintPass, LintPass};
-use rustc::hir::intravisit::FnKind;
-use rustc::lint;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{GenericParamKind, PatKind};
 use rustc_span::symbol::sym;
 use rustc_span::{symbol::Ident, BytePos, Span};
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::errors::Applicability;
 
 #[derive(PartialEq)]
 pub enum MethodLateContext {
@@ -352,7 +350,20 @@
     }
 
     fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat<'_>) {
-        if let &PatKind::Binding(_, _, ident, _) = &p.kind {
+        if let &PatKind::Binding(_, hid, ident, _) = &p.kind {
+            if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
+            {
+                if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind {
+                    for field in field_pats.iter() {
+                        if field.ident != ident {
+                            // Only check if a new name has been introduced, to avoid warning
+                            // on both the struct definition and this pattern.
+                            self.check_snake_case(cx, "variable", &ident);
+                        }
+                    }
+                    return;
+                }
+            }
             self.check_snake_case(cx, "variable", &ident);
         }
     }
diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs
new file mode 100644
index 0000000..7e5d670
--- /dev/null
+++ b/src/librustc_lint/passes.rs
@@ -0,0 +1,284 @@
+use crate::context::{EarlyContext, LateContext};
+
+use rustc_data_structures::sync;
+use rustc_hir as hir;
+use rustc_session::lint::builtin::HardwiredLints;
+use rustc_session::lint::LintPass;
+use rustc_span::Span;
+use syntax::ast;
+
+#[macro_export]
+macro_rules! late_lint_methods {
+    ($macro:path, $args:tt, [$hir:tt]) => (
+        $macro!($args, [$hir], [
+            fn check_param(a: &$hir hir::Param<$hir>);
+            fn check_body(a: &$hir hir::Body<$hir>);
+            fn check_body_post(a: &$hir hir::Body<$hir>);
+            fn check_name(a: Span, b: ast::Name);
+            fn check_crate(a: &$hir hir::Crate<$hir>);
+            fn check_crate_post(a: &$hir hir::Crate<$hir>);
+            fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
+            fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
+            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
+            fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
+            fn check_item(a: &$hir hir::Item<$hir>);
+            fn check_item_post(a: &$hir hir::Item<$hir>);
+            fn check_local(a: &$hir hir::Local<$hir>);
+            fn check_block(a: &$hir hir::Block<$hir>);
+            fn check_block_post(a: &$hir hir::Block<$hir>);
+            fn check_stmt(a: &$hir hir::Stmt<$hir>);
+            fn check_arm(a: &$hir hir::Arm<$hir>);
+            fn check_pat(a: &$hir hir::Pat<$hir>);
+            fn check_expr(a: &$hir hir::Expr<$hir>);
+            fn check_expr_post(a: &$hir hir::Expr<$hir>);
+            fn check_ty(a: &$hir hir::Ty<$hir>);
+            fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
+            fn check_generics(a: &$hir hir::Generics<$hir>);
+            fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
+            fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
+            fn check_fn(
+                a: rustc_hir::intravisit::FnKind<$hir>,
+                b: &$hir hir::FnDecl<$hir>,
+                c: &$hir hir::Body<$hir>,
+                d: Span,
+                e: hir::HirId);
+            fn check_fn_post(
+                a: rustc_hir::intravisit::FnKind<$hir>,
+                b: &$hir hir::FnDecl<$hir>,
+                c: &$hir hir::Body<$hir>,
+                d: Span,
+                e: hir::HirId
+            );
+            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
+            fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
+            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
+            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
+            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
+            fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
+            fn check_struct_field(a: &$hir hir::StructField<$hir>);
+            fn check_variant(a: &$hir hir::Variant<$hir>);
+            fn check_variant_post(a: &$hir hir::Variant<$hir>);
+            fn check_lifetime(a: &$hir hir::Lifetime);
+            fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
+            fn check_attribute(a: &$hir ast::Attribute);
+
+            /// Called when entering a syntax node that can have lint attributes such
+            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
+            fn enter_lint_attrs(a: &$hir [ast::Attribute]);
+
+            /// Counterpart to `enter_lint_attrs`.
+            fn exit_lint_attrs(a: &$hir [ast::Attribute]);
+        ]);
+    )
+}
+
+/// Trait for types providing lint checks.
+///
+/// Each `check` method checks a single syntax node, and should not
+/// invoke methods recursively (unlike `Visitor`). By default they
+/// do nothing.
+//
+// FIXME: eliminate the duplication with `Visitor`. But this also
+// contains a few lint-specific methods with no equivalent in `Visitor`.
+
+macro_rules! expand_lint_pass_methods {
+    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
+    )
+}
+
+macro_rules! declare_late_lint_pass {
+    ([], [$hir:tt], [$($methods:tt)*]) => (
+        pub trait LateLintPass<'a, $hir>: LintPass {
+            expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
+        }
+    )
+}
+
+late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
+
+impl LateLintPass<'_, '_> for HardwiredLints {}
+
+#[macro_export]
+macro_rules! expand_combined_late_lint_pass_method {
+    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$passes.$name $params;)*
+    })
+}
+
+#[macro_export]
+macro_rules! expand_combined_late_lint_pass_methods {
+    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) {
+            expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
+        })*
+    )
+}
+
+#[macro_export]
+macro_rules! declare_combined_late_lint_pass {
+    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
+        #[allow(non_snake_case)]
+        $v struct $name {
+            $($passes: $passes,)*
+        }
+
+        impl $name {
+            $v fn new() -> Self {
+                Self {
+                    $($passes: $constructor,)*
+                }
+            }
+
+            $v fn get_lints() -> LintArray {
+                let mut lints = Vec::new();
+                $(lints.extend_from_slice(&$passes::get_lints());)*
+                lints
+            }
+        }
+
+        impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
+            expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
+        }
+
+        #[allow(rustc::lint_pass_impl_without_macro)]
+        impl LintPass for $name {
+            fn name(&self) -> &'static str {
+                panic!()
+            }
+        }
+    )
+}
+
+#[macro_export]
+macro_rules! early_lint_methods {
+    ($macro:path, $args:tt) => (
+        $macro!($args, [
+            fn check_param(a: &ast::Param);
+            fn check_ident(a: ast::Ident);
+            fn check_crate(a: &ast::Crate);
+            fn check_crate_post(a: &ast::Crate);
+            fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId);
+            fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId);
+            fn check_foreign_item(a: &ast::ForeignItem);
+            fn check_foreign_item_post(a: &ast::ForeignItem);
+            fn check_item(a: &ast::Item);
+            fn check_item_post(a: &ast::Item);
+            fn check_local(a: &ast::Local);
+            fn check_block(a: &ast::Block);
+            fn check_block_post(a: &ast::Block);
+            fn check_stmt(a: &ast::Stmt);
+            fn check_arm(a: &ast::Arm);
+            fn check_pat(a: &ast::Pat);
+            fn check_pat_post(a: &ast::Pat);
+            fn check_expr(a: &ast::Expr);
+            fn check_expr_post(a: &ast::Expr);
+            fn check_ty(a: &ast::Ty);
+            fn check_generic_param(a: &ast::GenericParam);
+            fn check_generics(a: &ast::Generics);
+            fn check_where_predicate(a: &ast::WherePredicate);
+            fn check_poly_trait_ref(a: &ast::PolyTraitRef,
+                                    b: &ast::TraitBoundModifier);
+            fn check_fn(a: syntax::visit::FnKind<'_>, b: &ast::FnDecl, c: Span, d_: ast::NodeId);
+            fn check_fn_post(
+                a: syntax::visit::FnKind<'_>,
+                b: &ast::FnDecl,
+                c: Span,
+                d: ast::NodeId
+            );
+            fn check_trait_item(a: &ast::AssocItem);
+            fn check_trait_item_post(a: &ast::AssocItem);
+            fn check_impl_item(a: &ast::AssocItem);
+            fn check_impl_item_post(a: &ast::AssocItem);
+            fn check_struct_def(a: &ast::VariantData);
+            fn check_struct_def_post(a: &ast::VariantData);
+            fn check_struct_field(a: &ast::StructField);
+            fn check_variant(a: &ast::Variant);
+            fn check_variant_post(a: &ast::Variant);
+            fn check_lifetime(a: &ast::Lifetime);
+            fn check_path(a: &ast::Path, b: ast::NodeId);
+            fn check_attribute(a: &ast::Attribute);
+            fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
+            fn check_mac(a: &ast::Mac);
+
+            /// Called when entering a syntax node that can have lint attributes such
+            /// as `#[allow(...)]`. Called with *all* the attributes of that node.
+            fn enter_lint_attrs(a: &[ast::Attribute]);
+
+            /// Counterpart to `enter_lint_attrs`.
+            fn exit_lint_attrs(a: &[ast::Attribute]);
+        ]);
+    )
+}
+
+macro_rules! expand_early_lint_pass_methods {
+    ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
+    )
+}
+
+macro_rules! declare_early_lint_pass {
+    ([], [$($methods:tt)*]) => (
+        pub trait EarlyLintPass: LintPass {
+            expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
+        }
+    )
+}
+
+early_lint_methods!(declare_early_lint_pass, []);
+
+#[macro_export]
+macro_rules! expand_combined_early_lint_pass_method {
+    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$passes.$name $params;)*
+    })
+}
+
+#[macro_export]
+macro_rules! expand_combined_early_lint_pass_methods {
+    ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
+            expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
+        })*
+    )
+}
+
+#[macro_export]
+macro_rules! declare_combined_early_lint_pass {
+    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
+        #[allow(non_snake_case)]
+        $v struct $name {
+            $($passes: $passes,)*
+        }
+
+        impl $name {
+            $v fn new() -> Self {
+                Self {
+                    $($passes: $constructor,)*
+                }
+            }
+
+            $v fn get_lints() -> LintArray {
+                let mut lints = Vec::new();
+                $(lints.extend_from_slice(&$passes::get_lints());)*
+                lints
+            }
+        }
+
+        impl EarlyLintPass for $name {
+            expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
+        }
+
+        #[allow(rustc::lint_pass_impl_without_macro)]
+        impl LintPass for $name {
+            fn name(&self) -> &'static str {
+                panic!()
+            }
+        }
+    )
+}
+
+/// A lint pass boxed up as a trait object.
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
+pub type LateLintPassObject =
+    Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>;
diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs
index 8dbf96a..21b244a 100644
--- a/src/librustc_lint/redundant_semicolon.rs
+++ b/src/librustc_lint/redundant_semicolon.rs
@@ -1,6 +1,6 @@
-use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_errors::Applicability;
 use syntax::ast::{ExprKind, Stmt, StmtKind};
-use syntax::errors::Applicability;
 
 declare_lint! {
     pub REDUNDANT_SEMICOLON,
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index f740bdb..674a82b 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1,22 +1,20 @@
 #![allow(non_snake_case)]
 
-use crate::hir::def_id::DefId;
-use lint::{LateContext, LintArray, LintContext};
-use lint::{LateLintPass, LintPass};
-use rustc::lint;
+use crate::{LateContext, LateLintPass, LintContext};
 use rustc::mir::interpret::{sign_extend, truncate};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, ExprKind, Node};
 use rustc_index::vec::Idx;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
-use syntax::errors::Applicability;
 use syntax::{ast, attr};
 
 use log::debug;
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 184651e..bb2c4fa 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -1,21 +1,18 @@
-use lint::{EarlyContext, LateContext, LintArray, LintContext};
-use lint::{EarlyLintPass, LateLintPass, LintPass};
-use rustc::lint;
-use rustc::lint::builtin::UNUSED_ATTRIBUTES;
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty::adjustment;
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, Applicability};
 use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-
+use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
 use syntax::ast;
 use syntax::attr;
-use syntax::errors::{pluralize, Applicability};
 use syntax::print::pprust;
 use syntax::util::parser;
 
@@ -147,7 +144,7 @@
                 ty::Opaque(def, _) => {
                     let mut has_emitted = false;
                     for (predicate, _) in cx.tcx.predicates_of(def).predicates {
-                        if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
+                        if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
                             let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
                             let def_id = trait_ref.def_id;
                             let descr_pre =
@@ -547,12 +544,20 @@
     }
 
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
-        if let ast::StmtKind::Local(ref local) = s.kind {
-            self.check_unused_parens_pat(cx, &local.pat, false, false);
+        use ast::StmtKind::*;
 
-            if let Some(ref value) = local.init {
-                self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None);
+        match s.kind {
+            Local(ref local) => {
+                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);
+                }
             }
+            Expr(ref expr) => {
+                self.check_unused_parens_expr(cx, &expr, "block return value", false, None, None);
+            }
+            _ => {}
         }
     }
 
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index dff20f8..405ce03 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -215,12 +215,14 @@
     let mut cmd = Command::new(&llvm_config);
     cmd.arg(llvm_link_arg).arg("--ldflags");
     for lib in output(&mut cmd).split_whitespace() {
-        if lib.starts_with("-LIBPATH:") {
-            println!("cargo:rustc-link-search=native={}", &lib[9..]);
-        } else if is_crossed {
-            if lib.starts_with("-L") {
+        if is_crossed {
+            if lib.starts_with("-LIBPATH:") {
+                println!("cargo:rustc-link-search=native={}", lib[9..].replace(&host, &target));
+            } else if lib.starts_with("-L") {
                 println!("cargo:rustc-link-search=native={}", lib[2..].replace(&host, &target));
             }
+        } else if lib.starts_with("-LIBPATH:") {
+            println!("cargo:rustc-link-search=native={}", &lib[9..]);
         } else if lib.starts_with("-l") {
             println!("cargo:rustc-link-lib={}", &lib[2..]);
         } else if lib.starts_with("-L") {
diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml
deleted file mode 100644
index 9a24361..0000000
--- a/src/librustc_lsan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_lsan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_lsan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
deleted file mode 100644
index 6201bc9..0000000
--- a/src/librustc_lsan/build.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-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();
-
-        let (native, target) = match sanitizer_lib_boilerplate("lsan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_lsan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index d998e82..6da5847 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -16,8 +16,8 @@
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_target = { path = "../librustc_target" }
 rustc_index = { path = "../librustc_index" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
@@ -26,4 +26,6 @@
 rustc_expand = { path = "../librustc_expand" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index cfd7b76..351e72d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -6,32 +6,28 @@
 use rustc::hir::map::Definitions;
 use rustc::middle::cstore::DepKind;
 use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
-use rustc::session::config::{self, Sanitizer};
+use rustc::session::config;
 use rustc::session::search_paths::PathKind;
 use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
-use rustc_hir::def_id::CrateNum;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_index::vec::IndexVec;
-use rustc_target::spec::{PanicStrategy, TargetTriple};
-
-use std::path::Path;
-use std::{cmp, fs};
-
-use log::{debug, info, log_enabled};
-use proc_macro::bridge::client::ProcMacro;
+use rustc_errors::struct_span_err;
 use rustc_expand::base::SyntaxExtension;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_index::vec::IndexVec;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::{PanicStrategy, TargetTriple};
 use syntax::ast;
 use syntax::attr;
 use syntax::expand::allocator::{global_allocator_spans, AllocatorKind};
-use syntax::span_fatal;
 
-use rustc_error_codes::*;
+use log::{debug, info, log_enabled};
+use proc_macro::bridge::client::ProcMacro;
+use std::path::Path;
+use std::{cmp, fs};
 
 #[derive(Clone)]
 pub struct CStore {
@@ -261,7 +257,7 @@
         if self.local_crate_name == root.name()
             && self.sess.local_crate_disambiguator() == root.disambiguator()
         {
-            span_fatal!(
+            struct_span_err!(
                 self.sess,
                 span,
                 E0519,
@@ -271,6 +267,7 @@
                          will result in symbol conflicts between the two.",
                 root.name()
             )
+            .emit()
         }
 
         // Check for conflicts with any crate loaded so far
@@ -280,7 +277,7 @@
                other.hash() != root.hash()
             {
                 // but different SVH
-                span_fatal!(
+                struct_span_err!(
                     self.sess,
                     span,
                     E0523,
@@ -289,6 +286,7 @@
                          will result in symbol conflicts between the two.",
                     root.name()
                 )
+                .emit();
             }
         });
     }
@@ -672,108 +670,6 @@
         self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
     }
 
-    fn inject_sanitizer_runtime(&mut self) {
-        if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
-            // Sanitizers can only be used on some tested platforms with
-            // executables linked to `std`
-            const ASAN_SUPPORTED_TARGETS: &[&str] =
-                &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-            const TSAN_SUPPORTED_TARGETS: &[&str] =
-                &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-            const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-            const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-
-            let supported_targets = match *sanitizer {
-                Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
-                Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
-                Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
-                Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
-            };
-            if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) {
-                self.sess.err(&format!(
-                    "{:?}Sanitizer only works with the `{}` target",
-                    sanitizer,
-                    supported_targets.join("` or `")
-                ));
-                return;
-            }
-
-            // firstyear 2017 - during testing I was unable to access an OSX machine
-            // to make this work on different crate types. As a result, today I have
-            // only been able to test and support linux as a target.
-            if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" {
-                if !self.sess.crate_types.borrow().iter().all(|ct| {
-                    match *ct {
-                        // Link the runtime
-                        config::CrateType::Executable => true,
-                        // This crate will be compiled with the required
-                        // instrumentation pass
-                        config::CrateType::Staticlib
-                        | config::CrateType::Rlib
-                        | config::CrateType::Dylib
-                        | config::CrateType::Cdylib => false,
-                        _ => {
-                            self.sess.err(&format!(
-                                "Only executables, staticlibs, \
-                                cdylibs, dylibs and rlibs can be compiled with \
-                                `-Z sanitizer`"
-                            ));
-                            false
-                        }
-                    }
-                }) {
-                    return;
-                }
-            } else {
-                if !self.sess.crate_types.borrow().iter().all(|ct| {
-                    match *ct {
-                        // Link the runtime
-                        config::CrateType::Executable => true,
-                        // This crate will be compiled with the required
-                        // instrumentation pass
-                        config::CrateType::Rlib => false,
-                        _ => {
-                            self.sess.err(&format!(
-                                "Only executables and rlibs can be \
-                                                    compiled with `-Z sanitizer`"
-                            ));
-                            false
-                        }
-                    }
-                }) {
-                    return;
-                }
-            }
-
-            let mut uses_std = false;
-            self.cstore.iter_crate_data(|_, data| {
-                if data.name() == sym::std {
-                    uses_std = true;
-                }
-            });
-
-            if uses_std {
-                let name = Symbol::intern(match sanitizer {
-                    Sanitizer::Address => "rustc_asan",
-                    Sanitizer::Leak => "rustc_lsan",
-                    Sanitizer::Memory => "rustc_msan",
-                    Sanitizer::Thread => "rustc_tsan",
-                });
-                info!("loading sanitizer: {}", name);
-
-                let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None);
-                let data = self.cstore.get_crate_data(cnum);
-
-                // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
-                if !data.is_sanitizer_runtime() {
-                    self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name));
-                }
-            } else {
-                self.sess.err("Must link std to be compiled with `-Z sanitizer`");
-            }
-        }
-    }
-
     fn inject_profiler_runtime(&mut self) {
         if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() {
             info!("loading profiler");
@@ -925,7 +821,6 @@
     }
 
     pub fn postprocess(&mut self, krate: &ast::Crate) {
-        self.inject_sanitizer_runtime();
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
         self.inject_panic_runtime(krate);
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index 3427de1..375f372 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -83,14 +83,17 @@
     }
 
     let preferred_linkage = match ty {
-        // cdylibs must have all static dependencies.
-        config::CrateType::Cdylib => Linkage::Static,
-
         // Generating a dylib without `-C prefer-dynamic` means that we're going
         // to try to eagerly statically link all dependencies. This is normally
         // done for end-product dylibs, not intermediate products.
-        config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
-        config::CrateType::Dylib => Linkage::Dynamic,
+        //
+        // Treat cdylibs similarly. If `-C prefer-dynamic` is set, the caller may
+        // be code-size conscious, but without it, it makes sense to statically
+        // link a cdylib.
+        config::CrateType::Dylib | config::CrateType::Cdylib if !sess.opts.cg.prefer_dynamic => {
+            Linkage::Static
+        }
+        config::CrateType::Dylib | config::CrateType::Cdylib => Linkage::Dynamic,
 
         // If the global prefer_dynamic switch is turned off, or the final
         // executable will be statically linked, prefer static crate linkage.
@@ -122,10 +125,9 @@
             return v;
         }
 
-        // Staticlibs, cdylibs, and static executables must have all static
-        // dependencies. If any are not found, generate some nice pretty errors.
-        if ty == config::CrateType::Cdylib
-            || ty == config::CrateType::Staticlib
+        // Staticlibs and static executables must have all static dependencies.
+        // If any are not found, generate some nice pretty errors.
+        if ty == config::CrateType::Staticlib
             || (ty == config::CrateType::Executable
                 && sess.crt_static()
                 && !sess.target.target.options.crt_static_allows_dylibs)
diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs
index fa4983d..f04d023 100644
--- a/src/librustc_metadata/dynamic_lib.rs
+++ b/src/librustc_metadata/dynamic_lib.rs
@@ -111,9 +111,9 @@
     ) -> Result<*mut u8, String> {
         check_for_errors_in(|| libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8)
     }
+
     pub(super) unsafe fn close(handle: *mut u8) {
         libc::dlclose(handle as *mut libc::c_void);
-        ()
     }
 }
 
@@ -124,27 +124,15 @@
     use std::os::windows::prelude::*;
     use std::ptr;
 
-    use libc::{c_char, c_uint, c_void};
-
-    type DWORD = u32;
-    type HMODULE = *mut u8;
-    type BOOL = i32;
-    type LPCWSTR = *const u16;
-    type LPCSTR = *const i8;
-
-    extern "system" {
-        fn SetThreadErrorMode(dwNewMode: DWORD, lpOldMode: *mut DWORD) -> c_uint;
-        fn LoadLibraryW(name: LPCWSTR) -> HMODULE;
-        fn GetModuleHandleExW(dwFlags: DWORD, name: LPCWSTR, handle: *mut HMODULE) -> BOOL;
-        fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void;
-        fn FreeLibrary(handle: HMODULE) -> BOOL;
-    }
+    use winapi::shared::minwindef::HMODULE;
+    use winapi::um::errhandlingapi::SetThreadErrorMode;
+    use winapi::um::libloaderapi::{FreeLibrary, GetModuleHandleExW, GetProcAddress, LoadLibraryW};
+    use winapi::um::winbase::SEM_FAILCRITICALERRORS;
 
     pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
         // disable "dll load failed" error dialog.
         let prev_error_mode = unsafe {
-            // SEM_FAILCRITICALERRORS 0x01
-            let new_error_mode = 1;
+            let new_error_mode = SEM_FAILCRITICALERRORS;
             let mut prev_error_mode = 0;
             let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode);
             if result == 0 {
@@ -156,12 +144,12 @@
         let result = match filename {
             Some(filename) => {
                 let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect();
-                let result = unsafe { LoadLibraryW(filename_str.as_ptr()) };
+                let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8;
                 ptr_result(result)
             }
             None => {
                 let mut handle = ptr::null_mut();
-                let succeeded = unsafe { GetModuleHandleExW(0 as DWORD, ptr::null(), &mut handle) };
+                let succeeded = unsafe { GetModuleHandleExW(0, ptr::null(), &mut handle) };
                 if succeeded == 0 {
                     Err(io::Error::last_os_error().to_string())
                 } else {
@@ -177,7 +165,10 @@
         result
     }
 
-    pub(super) unsafe fn symbol(handle: *mut u8, symbol: *const c_char) -> Result<*mut u8, String> {
+    pub(super) unsafe fn symbol(
+        handle: *mut u8,
+        symbol: *const libc::c_char,
+    ) -> Result<*mut u8, String> {
         let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8;
         ptr_result(ptr)
     }
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 0fec4bf..cf925ab 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -10,7 +10,7 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![feature(rustc_private)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 59e769c..2157b8c 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -222,13 +222,10 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
-
-use errors::DiagnosticBuilder;
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
-use syntax::struct_span_err;
-use syntax::{span_err, span_fatal};
 
 use std::cmp;
 use std::fmt;
@@ -244,8 +241,6 @@
 
 use log::{debug, info, warn};
 
-use rustc_error_codes::*;
-
 #[derive(Clone)]
 struct CrateMismatch {
     path: PathBuf,
@@ -659,14 +654,36 @@
         dylibs: FxHashMap<PathBuf, PathKind>,
     ) -> Option<(Svh, Library)> {
         let mut slot = None;
+        // Order here matters, rmeta should come first. See comment in
+        // `extract_one` below.
         let source = CrateSource {
-            rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
             rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot),
+            rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
             dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot),
         };
         slot.map(|(svh, metadata)| (svh, Library { source, metadata }))
     }
 
+    fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool {
+        if flavor == CrateFlavor::Dylib && self.is_proc_macro == Some(true) {
+            return true;
+        }
+
+        // The all loop is because `--crate-type=rlib --crate-type=rlib` is
+        // legal and produces both inside this type.
+        let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == config::CrateType::Rlib);
+        let needs_object_code = self.sess.opts.output_types.should_codegen();
+        // If we're producing an rlib, then we don't need object code.
+        // Or, if we're not producing object code, then we don't need it either
+        // (e.g., if we're a cdylib but emitting just metadata).
+        if is_rlib || !needs_object_code {
+            flavor == CrateFlavor::Rmeta
+        } else {
+            // we need all flavors (perhaps not true, but what we do for now)
+            true
+        }
+    }
+
     // Attempts to extract *one* library from the set `m`. If the set has no
     // elements, `None` is returned. If the set has more than one element, then
     // the errors and notes are emitted about the set of libraries.
@@ -684,12 +701,22 @@
         let mut ret: Option<(PathBuf, PathKind)> = None;
         let mut error = 0;
 
+        // If we are producing an rlib, and we've already loaded metadata, then
+        // we should not attempt to discover further crate sources (unless we're
+        // locating a proc macro; exact logic is in needs_crate_flavor). This means
+        // that under -Zbinary-dep-depinfo we will not emit a dependency edge on
+        // the *unused* rlib, and by returning `None` here immediately we
+        // guarantee that we do indeed not use it.
+        //
+        // See also #68149 which provides more detail on why emitting the
+        // dependency on the rlib is a bad thing.
+        //
+        // We currenty do not verify that these other sources are even in sync,
+        // and this is arguably a bug (see #10786), but because reading metadata
+        // is quite slow (especially from dylibs) we currently do not read it
+        // from the other crate sources.
         if slot.is_some() {
-            // FIXME(#10786): for an optimization, we only read one of the
-            //                libraries' metadata sections. In theory we should
-            //                read both, but reading dylib metadata is quite
-            //                slow.
-            if m.is_empty() {
+            if m.is_empty() || !self.needs_crate_flavor(flavor) {
                 return None;
             } else if m.len() == 1 {
                 return Some(m.into_iter().next().unwrap());
@@ -1038,28 +1065,28 @@
     };
 
     if target_only {
-        // Need to abort before syntax expansion.
         let message = format!(
-            "plugin `{}` is not available for triple `{}` \
-                                (only found {})",
+            "plugin `{}` is not available for triple `{}` (only found {})",
             name,
             config::host_triple(),
             sess.opts.target_triple
         );
-        span_fatal!(sess, span, E0456, "{}", &message);
+        struct_span_err!(sess, span, E0456, "{}", &message).emit();
+        return None;
     }
 
     match library.source.dylib {
         Some(dylib) => Some((dylib.0, library.metadata.get_root().disambiguator())),
         None => {
-            span_err!(
+            struct_span_err!(
                 sess,
                 span,
                 E0457,
                 "plugin `{}` only found in rlib format, but must be available \
                         in dylib format",
                 name
-            );
+            )
+            .emit();
             // No need to abort because the loading code will just ignore this
             // empty dylib.
             None
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index c524d20..bbf6973 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -1,17 +1,15 @@
 use rustc::middle::cstore::{self, NativeLibrary};
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
 use syntax::attr;
-use syntax::feature_gate::feature_err;
-use syntax::{span_err, struct_span_err};
-
-use rustc_error_codes::*;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     let mut collector = Collector { tcx, libs: Vec::new() };
@@ -159,7 +157,7 @@
         if lib.kind == cstore::NativeFramework && !is_osx {
             let msg = "native frameworks are only available on macOS targets";
             match span {
-                Some(span) => span_err!(self.tcx.sess, span, E0455, "{}", msg),
+                Some(span) => struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit(),
                 None => self.tcx.sess.err(msg),
             }
         }
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 77d1436..6280121 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -16,8 +16,8 @@
 use rustc::session::Session;
 use rustc::ty::codec::TyDecoder;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::util::captures::Captures;
 use rustc::util::common::record_time;
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
@@ -840,7 +840,7 @@
 
     fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
         match self.is_proc_macro(id) {
-            true => self.root.proc_macro_stability.clone(),
+            true => self.root.proc_macro_stability,
             false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)),
         }
     }
@@ -1587,10 +1587,6 @@
         self.root.panic_runtime
     }
 
-    crate fn is_sanitizer_runtime(&self) -> bool {
-        self.root.sanitizer_runtime
-    }
-
     crate fn is_profiler_runtime(&self) -> bool {
         self.root.profiler_runtime
     }
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index ba3c4e4..fb7e554 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -161,7 +161,6 @@
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
     has_panic_handler => { cdata.root.has_panic_handler }
-    is_sanitizer_runtime => { cdata.root.sanitizer_runtime }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
     extern_crate => {
@@ -478,6 +477,14 @@
     pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource {
         self.get_crate_data(cnum).source.clone()
     }
+
+    pub fn get_span_untracked(&self, def_id: DefId, sess: &Session) -> Span {
+        self.get_crate_data(def_id.krate).get_span(def_id.index, sess)
+    }
+
+    pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
+        self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes
+    }
 }
 
 impl CrateStore for CStore {
@@ -485,10 +492,6 @@
         self
     }
 
-    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
-        self.get_crate_data(def.krate).get_generics(def.index, sess)
-    }
-
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol {
         self.get_crate_data(cnum).root.name
     }
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 92bfc51..9d2bea2 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -2,6 +2,7 @@
 use crate::rmeta::*;
 
 use rustc::hir::map::definitions::DefPathTable;
+use rustc::hir::map::Map;
 use rustc::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary};
 use rustc::middle::dependency_format::Linkage;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
@@ -35,9 +36,8 @@
 use syntax::attr;
 use syntax::expand::is_proc_macro_attr;
 
-use rustc::hir::intravisit;
-use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
 struct EncodeContext<'tcx> {
@@ -504,7 +504,7 @@
             },
             proc_macro_data,
             proc_macro_stability: if is_proc_macro {
-                tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone())
+                tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| *stab)
             } else {
                 None
             },
@@ -514,7 +514,6 @@
             no_builtins: attr::contains_name(&attrs, sym::no_builtins),
             panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
             profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
-            sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime),
             symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
 
             crate_deps,
@@ -1074,7 +1073,7 @@
                     ctor: None,
                 }), adt_def.repr)
             }
-            hir::ItemKind::Impl(_, _, defaultness, ..) => {
+            hir::ItemKind::Impl { defaultness, .. } => {
                 let trait_ref = self.tcx.impl_trait_ref(def_id);
                 let polarity = self.tcx.impl_polarity(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
@@ -1150,7 +1149,7 @@
                     })
                 )
             }
-            hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => {
+            hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
                 record!(self.per_def.children[def_id] <-
                     associated_item_def_ids.iter().map(|&def_id| {
@@ -1173,13 +1172,13 @@
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Union(..)
-            | hir::ItemKind::Impl(..) => self.encode_item_type(def_id),
+            | hir::ItemKind::Impl { .. } => self.encode_item_type(def_id),
             _ => {}
         }
         if let hir::ItemKind::Fn(..) = item.kind {
             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
         }
-        if let hir::ItemKind::Impl(..) = item.kind {
+        if let hir::ItemKind::Impl { .. } = item.kind {
             if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
                 record!(self.per_def.impl_trait_ref[def_id] <- trait_ref);
             }
@@ -1200,7 +1199,7 @@
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Union(..)
-            | hir::ItemKind::Impl(..)
+            | hir::ItemKind::Impl { .. }
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Trait(..)
             | hir::ItemKind::TraitAlias(..) => {
@@ -1520,7 +1519,9 @@
 
 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
 impl Visitor<'tcx> for EncodeContext<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
@@ -1644,7 +1645,7 @@
             hir::ItemKind::Union(..) => {
                 self.encode_fields(def_id);
             }
-            hir::ItemKind::Impl(..) => {
+            hir::ItemKind::Impl { .. } => {
                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.encode_info_for_impl_item(trait_item_def_id);
                 }
@@ -1665,7 +1666,7 @@
 
 impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        if let hir::ItemKind::Impl(..) = item.kind {
+        if let hir::ItemKind::Impl { .. } = item.kind {
             let impl_id = self.tcx.hir().local_def_id(item.hir_id);
             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
                 self.impls.entry(trait_ref.def_id).or_default().push(impl_id.index);
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 6309f1c..426ea62 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -209,7 +209,6 @@
     no_builtins: bool,
     panic_runtime: bool,
     profiler_runtime: bool,
-    sanitizer_runtime: bool,
     symbol_mangling_version: SymbolManglingVersion,
 }
 
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 9b6908d..00881e3 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -10,7 +10,6 @@
 doctest = false
 
 [dependencies]
-arena = { path = "../libarena" }
 either = "1.5.0"
 dot = { path = "../libgraphviz", package = "graphviz" }
 itertools = "0.8"
@@ -30,4 +29,3 @@
 rustc_span = { path = "../librustc_span" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index b66b2e4..9d5cf3e 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -200,17 +200,15 @@
                 region,
                 reserve_location: location,
                 activation_location: TwoPhaseActivation::NotTwoPhase,
-                borrowed_place: borrowed_place.clone(),
-                assigned_place: assigned_place.clone(),
+                borrowed_place: *borrowed_place,
+                assigned_place: *assigned_place,
             };
             let idx = self.idx_vec.push(borrow);
             self.location_map.insert(location, idx);
 
             self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx);
 
-            if let mir::PlaceBase::Local(local) = borrowed_place.base {
-                self.local_map.entry(local).or_default().insert(idx);
-            }
+            self.local_map.entry(borrowed_place.local).or_default().insert(idx);
         }
 
         self.super_assign(assigned_place, rvalue, location)
diff --git a/src/librustc_mir/borrow_check/constraint_generation.rs b/src/librustc_mir/borrow_check/constraint_generation.rs
index 97de201..0f6a360 100644
--- a/src/librustc_mir/borrow_check/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/constraint_generation.rs
@@ -2,8 +2,8 @@
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
 use rustc::mir::{
-    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, PlaceRef, ProjectionElem,
-    Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
+    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue,
+    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
 };
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::SubstsRef;
@@ -16,7 +16,6 @@
 
 pub(super) fn generate_constraints<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     liveness_constraints: &mut LivenessValues<RegionVid>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
@@ -30,7 +29,6 @@
         location_table,
         all_facts,
         body,
-        param_env,
     };
 
     for (bb, data) in body.basic_blocks().iter_enumerated() {
@@ -41,7 +39,6 @@
 /// 'cg = the duration of the constraint generation process itself.
 struct ConstraintGeneration<'cg, 'cx, 'tcx> {
     infcx: &'cg InferCtxt<'cx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     all_facts: &'cg mut Option<AllFacts>,
     location_table: &'cg LocationTable,
     liveness_constraints: &'cg mut LivenessValues<RegionVid>,
@@ -191,11 +188,8 @@
             //   of the borrows are killed: the ones whose `borrowed_place`
             //   conflicts with the `place`.
             match place.as_ref() {
-                PlaceRef { base: &PlaceBase::Local(local), projection: &[] }
-                | PlaceRef {
-                    base: &PlaceBase::Local(local),
-                    projection: &[ProjectionElem::Deref],
-                } => {
+                PlaceRef { local, projection: &[] }
+                | PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
                     debug!(
                         "Recording `killed` facts for borrows of local={:?} at location={:?}",
                         local, location
@@ -205,16 +199,12 @@
                         all_facts,
                         self.borrow_set,
                         self.location_table,
-                        &local,
+                        local,
                         location,
                     );
                 }
 
-                PlaceRef { base: &PlaceBase::Static(_), .. } => {
-                    // Ignore kills of static or static mut variables.
-                }
-
-                PlaceRef { base: &PlaceBase::Local(local), projection: &[.., _] } => {
+                PlaceRef { local, projection: &[.., _] } => {
                     // Kill conflicting borrows of the innermost local.
                     debug!(
                         "Recording `killed` facts for borrows of \
@@ -222,11 +212,10 @@
                         local, location
                     );
 
-                    if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
+                    if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
                         for &borrow_index in borrow_indices {
                             let places_conflict = places_conflict::places_conflict(
                                 self.infcx.tcx,
-                                self.param_env,
                                 self.body,
                                 &self.borrow_set.borrows[borrow_index].borrowed_place,
                                 place,
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 7e25156..08333ae 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -1,7 +1,7 @@
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
-    FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceBase,
-    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
+    FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
+    ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
 };
 use rustc::traits::error_reporting::suggest_constraining_type_param;
 use rustc::ty::{self, Ty};
@@ -186,7 +186,7 @@
             }
 
             let ty =
-                Place::ty_from(used_place.base, used_place.projection, *self.body, self.infcx.tcx)
+                Place::ty_from(used_place.local, used_place.projection, *self.body, self.infcx.tcx)
                     .ty;
             let needs_note = match ty.kind {
                 ty::Closure(id, _) => {
@@ -597,15 +597,15 @@
                 // field access to a union. If we find that, then we will keep the place of the
                 // union being accessed and the field that was being accessed so we can check the
                 // second borrowed place for the same union and a access to a different field.
-                let Place { base, projection } = first_borrowed_place;
+                let Place { local, projection } = first_borrowed_place;
 
                 let mut cursor = projection.as_ref();
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
                     match elem {
-                        ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => {
-                            return Some((PlaceRef { base: base, projection: proj_base }, field));
+                        ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
+                            return Some((PlaceRef { local, projection: proj_base }, field));
                         }
                         _ => {}
                     }
@@ -615,21 +615,21 @@
             .and_then(|(target_base, target_field)| {
                 // With the place of a union and a field access into it, we traverse the second
                 // borrowed place and look for a access to a different field of the same union.
-                let Place { base, projection } = second_borrowed_place;
+                let Place { local, projection } = second_borrowed_place;
 
                 let mut cursor = projection.as_ref();
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
                     if let ProjectionElem::Field(field, _) = elem {
-                        if let Some(union_ty) = union_ty(base, proj_base) {
+                        if let Some(union_ty) = union_ty(local, proj_base) {
                             if field != target_field
-                                && base == target_base.base
+                                && local == target_base.local
                                 && proj_base == target_base.projection
                             {
                                 // FIXME when we avoid clone reuse describe_place closure
                                 let describe_base_place = self
-                                    .describe_place(PlaceRef { base: base, projection: proj_base })
+                                    .describe_place(PlaceRef { local, projection: proj_base })
                                     .unwrap_or_else(|| "_".to_owned());
 
                                 return Some((
@@ -686,15 +686,12 @@
         let borrow_span = borrow_spans.var_or_use();
 
         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,
-        };
+        let proper_span = self.body.local_decls[*root_place.local].source_info.span;
 
         let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
 
         if self.access_place_error_reported.contains(&(
-            Place { base: root_place.base.clone(), projection: root_place_projection },
+            Place { local: root_place.local.clone(), projection: root_place_projection },
             borrow_span,
         )) {
             debug!(
@@ -705,18 +702,17 @@
         }
 
         self.access_place_error_reported.insert((
-            Place { base: root_place.base.clone(), projection: root_place_projection },
+            Place { local: root_place.local.clone(), projection: root_place_projection },
             borrow_span,
         ));
 
-        if let PlaceBase::Local(local) = borrow.borrowed_place.base {
-            if self.body.local_decls[local].is_ref_to_thread_local() {
-                let err = self
-                    .report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
-                err.buffer(&mut self.errors_buffer);
-                return;
-            }
-        };
+        let borrowed_local = borrow.borrowed_place.local;
+        if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
+            let err =
+                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
+            err.buffer(&mut self.errors_buffer);
+            return;
+        }
 
         if let StorageDeadOrDrop::Destructor(dropped_ty) =
             self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
@@ -1142,12 +1138,7 @@
         } else {
             let root_place =
                 self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
-            let local =
-                if let PlaceRef { base: PlaceBase::Local(local), projection: [] } = root_place {
-                    local
-                } else {
-                    bug!("try_report_cannot_return_reference_to_local: not a local")
-                };
+            let local = root_place.local;
             match self.body.local_kind(*local) {
                 LocalKind::ReturnPointer | LocalKind::Temp => {
                     ("temporary value".to_string(), "temporary value created here".to_string())
@@ -1514,7 +1505,7 @@
             [proj_base @ .., elem] => {
                 // FIXME(spastorino) make this iterate
                 let base_access = self.classify_drop_access_kind(PlaceRef {
-                    base: place.base,
+                    local: place.local,
                     projection: proj_base,
                 });
                 match elem {
@@ -1522,7 +1513,9 @@
                         StorageDeadOrDrop::LocalStorageDead
                         | StorageDeadOrDrop::BoxedStorageDead => {
                             assert!(
-                                Place::ty_from(&place.base, proj_base, *self.body, tcx).ty.is_box(),
+                                Place::ty_from(&place.local, proj_base, *self.body, tcx)
+                                    .ty
+                                    .is_box(),
                                 "Drop of value behind a reference or raw pointer"
                             );
                             StorageDeadOrDrop::BoxedStorageDead
@@ -1530,7 +1523,7 @@
                         StorageDeadOrDrop::Destructor(_) => base_access,
                     },
                     ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = Place::ty_from(&place.base, proj_base, *self.body, tcx).ty;
+                        let base_ty = Place::ty_from(&place.local, proj_base, *self.body, tcx).ty;
                         match base_ty.kind {
                             ty::Adt(def, _) if def.has_dtor(tcx) => {
                                 // Report the outermost adt with a destructor
diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index 9a0c99b..01b7c56 100644
--- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -2,12 +2,13 @@
 
 use std::collections::VecDeque;
 
+use rustc::infer::NLLRegionVariableOrigin;
 use rustc::mir::{
     Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue,
     Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::adjustment::PointerCast;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_index::vec::IndexVec;
@@ -254,6 +255,23 @@
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
+    fn free_region_constraint_info(
+        &self,
+        borrow_region: RegionVid,
+        outlived_region: RegionVid,
+    ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
+        let (category, from_closure, span) = self.regioncx.best_blame_constraint(
+            &self.body,
+            borrow_region,
+            NLLRegionVariableOrigin::FreeRegion,
+            |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+        );
+
+        let outlived_fr_name = self.give_region_a_name(outlived_region);
+
+        (category, from_closure, span, outlived_fr_name)
+    }
+
     /// Returns structured explanation for *why* the borrow contains the
     /// point from `location`. This is key for the "3-point errors"
     /// [described in the NLL RFC][d].
@@ -278,14 +296,14 @@
             location, borrow, kind_place
         );
 
-        let regioncx = &self.nonlexical_regioncx;
+        let regioncx = &self.regioncx;
         let body: &Body<'_> = &self.body;
         let tcx = self.infcx.tcx;
 
         let borrow_region_vid = borrow.region;
         debug!("explain_why_borrow_contains_point: borrow_region_vid={:?}", borrow_region_vid);
 
-        let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, location);
+        let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
         debug!("explain_why_borrow_contains_point: region_sub={:?}", region_sub);
 
         match find_use::find(body, regioncx, tcx, region_sub, location) {
@@ -329,10 +347,9 @@
             }
 
             None => {
-                if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) {
-                    let (category, from_closure, span, region_name) = self
-                        .nonlexical_regioncx
-                        .free_region_constraint_info(self, borrow_region_vid, region);
+                if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
+                    let (category, from_closure, span, region_name) =
+                        self.free_region_constraint_info(borrow_region_vid, region);
                     if let Some(region_name) = region_name {
                         let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
                         BorrowExplanation::MustBeValidFor {
@@ -345,14 +362,14 @@
                     } else {
                         debug!(
                             "explain_why_borrow_contains_point: \
-                                Could not generate a region name"
+                             Could not generate a region name"
                         );
                         BorrowExplanation::Unexplained
                     }
                 } else {
                     debug!(
                         "explain_why_borrow_contains_point: \
-                            Could not generate an error region vid"
+                         Could not generate an error region vid"
                     );
                     BorrowExplanation::Unexplained
                 }
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index c8a5933..0fc73d3 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -2,8 +2,7 @@
 
 use rustc::mir::{
     AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
-    PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Static, StaticKind,
-    Terminator, TerminatorKind,
+    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::print::Print;
@@ -33,7 +32,7 @@
 crate use mutability_errors::AccessKind;
 crate use outlives_suggestion::OutlivesSuggestionBuilder;
 crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
-crate use region_name::{RegionErrorNamingCtx, RegionName, RegionNameSource};
+crate use region_name::{RegionName, RegionNameSource};
 
 pub(super) struct IncludingDowncast(pub(super) bool);
 
@@ -169,42 +168,30 @@
         including_downcast: &IncludingDowncast,
     ) -> Result<(), ()> {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 self.append_local_to_string(*local, buf)?;
             }
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }),
-                projection: [],
-            } => {
-                buf.push_str("promoted");
-            }
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }),
-                projection: [],
-            } => {
-                buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string());
-            }
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_for_guard() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_for_guard() =>
             {
                 self.append_place_to_string(
-                    PlaceRef { base: &PlaceBase::Local(local), projection: &[] },
+                    PlaceRef { local: local, projection: &[] },
                     buf,
                     autoderef,
                     &including_downcast,
                 )?;
             }
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_to_static() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_to_static() =>
             {
-                let local_info = &self.body.local_decls[local].local_info;
+                let local_info = &self.body.local_decls[*local].local_info;
                 if let LocalInfo::StaticRef { def_id, .. } = *local_info {
                     buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
                 } else {
                     unreachable!();
                 }
             }
-            PlaceRef { base, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local, projection: [proj_base @ .., elem] } => {
                 match elem {
                     ProjectionElem::Deref => {
                         let upvar_field_projection = self.is_upvar_field_projection(place);
@@ -220,29 +207,25 @@
                             if autoderef {
                                 // FIXME turn this recursion into iteration
                                 self.append_place_to_string(
-                                    PlaceRef { base, projection: proj_base },
+                                    PlaceRef { local, projection: proj_base },
                                     buf,
                                     autoderef,
                                     &including_downcast,
                                 )?;
                             } else {
-                                match (proj_base, base) {
-                                    _ => {
-                                        buf.push_str(&"*");
-                                        self.append_place_to_string(
-                                            PlaceRef { base, projection: proj_base },
-                                            buf,
-                                            autoderef,
-                                            &including_downcast,
-                                        )?;
-                                    }
-                                }
+                                buf.push_str(&"*");
+                                self.append_place_to_string(
+                                    PlaceRef { local, projection: proj_base },
+                                    buf,
+                                    autoderef,
+                                    &including_downcast,
+                                )?;
                             }
                         }
                     }
                     ProjectionElem::Downcast(..) => {
                         self.append_place_to_string(
-                            PlaceRef { base, projection: proj_base },
+                            PlaceRef { local, projection: proj_base },
                             buf,
                             autoderef,
                             &including_downcast,
@@ -261,9 +244,9 @@
                             buf.push_str(&name);
                         } else {
                             let field_name = self
-                                .describe_field(PlaceRef { base, projection: proj_base }, *field);
+                                .describe_field(PlaceRef { local, projection: proj_base }, *field);
                             self.append_place_to_string(
-                                PlaceRef { base, projection: proj_base },
+                                PlaceRef { local, projection: proj_base },
                                 buf,
                                 autoderef,
                                 &including_downcast,
@@ -275,7 +258,7 @@
                         autoderef = true;
 
                         self.append_place_to_string(
-                            PlaceRef { base, projection: proj_base },
+                            PlaceRef { local, projection: proj_base },
                             buf,
                             autoderef,
                             &including_downcast,
@@ -292,7 +275,7 @@
                         // then use another while the borrow is held, don't output indices details
                         // to avoid confusing the end-user
                         self.append_place_to_string(
-                            PlaceRef { base, projection: proj_base },
+                            PlaceRef { local, projection: proj_base },
                             buf,
                             autoderef,
                             &including_downcast,
@@ -323,20 +306,18 @@
     fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
         // FIXME Place2 Make this work iteratively
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[*local];
                 self.describe_field_from_ty(&local.ty, field, None)
             }
-            PlaceRef { base: PlaceBase::Static(static_), projection: [] } => {
-                self.describe_field_from_ty(&static_.ty, field, None)
-            }
-            PlaceRef { base, projection: [proj_base @ .., elem] } => match elem {
+            PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
                 ProjectionElem::Deref => {
-                    self.describe_field(PlaceRef { base, projection: proj_base }, field)
+                    self.describe_field(PlaceRef { local, projection: proj_base }, field)
                 }
                 ProjectionElem::Downcast(_, variant_index) => {
                     let base_ty =
-                        Place::ty_from(place.base, place.projection, *self.body, self.infcx.tcx).ty;
+                        Place::ty_from(place.local, place.projection, *self.body, self.infcx.tcx)
+                            .ty;
                     self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
                 }
                 ProjectionElem::Field(_, field_type) => {
@@ -345,7 +326,7 @@
                 ProjectionElem::Index(..)
                 | ProjectionElem::ConstantIndex { .. }
                 | ProjectionElem::Subslice { .. } => {
-                    self.describe_field(PlaceRef { base, projection: proj_base }, field)
+                    self.describe_field(PlaceRef { local, projection: proj_base }, field)
                 }
             },
         }
@@ -466,7 +447,7 @@
 
         // If we didn't find an overloaded deref or index, then assume it's a
         // built in deref and check the type of the base.
-        let base_ty = Place::ty_from(deref_base.base, deref_base.projection, *self.body, tcx).ty;
+        let base_ty = Place::ty_from(deref_base.local, deref_base.projection, *self.body, tcx).ty;
         if base_ty.is_unsafe_ptr() {
             BorrowedContentSource::DerefRawPointer
         } else if base_ty.is_mutable_ptr() {
diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index 3f4204b..43121b3 100644
--- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -1,7 +1,8 @@
 use rustc::mir::*;
 use rustc::ty;
 use rustc_errors::{Applicability, DiagnosticBuilder};
-use rustc_span::Span;
+use rustc_span::source_map::DesugaringKind;
+use rustc_span::{Span, Symbol};
 
 use crate::borrow_check::diagnostics::UseSpans;
 use crate::borrow_check::prefixes::PrefixSet;
@@ -243,9 +244,6 @@
             );
             (
                 match kind {
-                    IllegalMoveOriginKind::Static => {
-                        unreachable!();
-                    }
                     IllegalMoveOriginKind::BorrowedContent { target_place } => self
                         .report_cannot_move_from_borrowed_content(
                             original_path,
@@ -276,7 +274,8 @@
         let description = if place.projection.len() == 1 {
             format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
         } else {
-            let base_static = PlaceRef { base: &place.base, projection: &[ProjectionElem::Deref] };
+            let base_static =
+                PlaceRef { local: &place.local, projection: &[ProjectionElem::Deref] };
 
             format!(
                 "`{:?}` as `{:?}` is a static item",
@@ -305,12 +304,12 @@
 
         let deref_base = match deref_target_place.projection.as_ref() {
             &[ref proj_base @ .., ProjectionElem::Deref] => {
-                PlaceRef { base: &deref_target_place.base, projection: &proj_base }
+                PlaceRef { local: &deref_target_place.local, projection: &proj_base }
             }
             _ => bug!("deref_target_place is not a deref projection"),
         };
 
-        if let PlaceRef { base: PlaceBase::Local(local), projection: [] } = deref_base {
+        if let PlaceRef { local, projection: [] } = deref_base {
             let decl = &self.body.local_decls[*local];
             if decl.is_ref_for_guard() {
                 let mut err = self.cannot_move_out_of(
@@ -385,10 +384,20 @@
                 }
             }
         };
-        let move_ty = format!("{:?}", move_place.ty(*self.body, self.infcx.tcx).ty,);
         if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
-            let is_option = move_ty.starts_with("std::option::Option");
-            let is_result = move_ty.starts_with("std::result::Result");
+            let def_id = match move_place.ty(*self.body, self.infcx.tcx).ty.kind {
+                ty::Adt(self_def, _) => self_def.did,
+                ty::Foreign(def_id)
+                | ty::FnDef(def_id, _)
+                | ty::Closure(def_id, _)
+                | ty::Generator(def_id, ..)
+                | ty::Opaque(def_id, _) => def_id,
+                _ => return err,
+            };
+            let is_option =
+                self.infcx.tcx.is_diagnostic_item(Symbol::intern("option_type"), def_id);
+            let is_result =
+                self.infcx.tcx.is_diagnostic_item(Symbol::intern("result_type"), def_id);
             if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
                 err.span_suggestion(
                     span,
@@ -399,6 +408,16 @@
                     format!("{}.as_ref()", snippet),
                     Applicability::MaybeIncorrect,
                 );
+            } else if span.is_desugaring(DesugaringKind::ForLoop)
+                && self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id)
+            {
+                // FIXME: suggest for anything that implements `IntoIterator`.
+                err.span_suggestion(
+                    span,
+                    "consider iterating over a slice of the `Vec<_>`'s content",
+                    format!("&{}", snippet),
+                    Applicability::MaybeIncorrect,
+                );
             }
         }
         err
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index 595acec..ae468e8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -1,5 +1,5 @@
 use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache};
-use rustc::mir::{Mutability, Place, PlaceBase, PlaceRef, ProjectionElem};
+use rustc::mir::{Mutability, Place, PlaceRef, ProjectionElem};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
 use rustc_hir::Node;
@@ -42,7 +42,7 @@
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
                 if access_place.as_local().is_some() {
                     reason = ", as it is not declared as mutable".to_string();
@@ -53,11 +53,11 @@
             }
 
             PlaceRef {
-                base: _,
+                local,
                 projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
                 debug_assert!(is_closure_or_generator(
-                    Place::ty_from(&the_place_err.base, proj_base, *self.body, self.infcx.tcx).ty
+                    Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
@@ -69,21 +69,21 @@
                 }
             }
 
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_for_guard() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_for_guard() =>
             {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
                 reason = ", as it is immutable for the pattern guard".to_string();
             }
-            PlaceRef { base: &PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
-                if self.body.local_decls[local].is_ref_to_static() =>
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
+                if self.body.local_decls[*local].is_ref_to_static() =>
             {
                 if access_place.projection.len() == 1 {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
                 } else {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
-                    let local_info = &self.body.local_decls[local].local_info;
+                    let local_info = &self.body.local_decls[*local].local_info;
                     if let LocalInfo::StaticRef { def_id, .. } = *local_info {
                         let static_name = &self.infcx.tcx.item_name(def_id);
                         reason = format!(", as `{}` is an immutable static item", static_name);
@@ -92,8 +92,8 @@
                     }
                 }
             }
-            PlaceRef { base: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
-                if the_place_err.base == &PlaceBase::Local(Local::new(1))
+            PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
+                if *the_place_err.local == Local::new(1)
                     && proj_base.is_empty()
                     && !self.upvars.is_empty()
                 {
@@ -101,7 +101,7 @@
                     debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
                         Place::ty_from(
-                            the_place_err.base,
+                            the_place_err.local,
                             the_place_err.projection,
                             *self.body,
                             self.infcx.tcx
@@ -116,7 +116,7 @@
                     }
                 } else {
                     let source = self.borrowed_content_source(PlaceRef {
-                        base: the_place_err.base,
+                        local: the_place_err.local,
                         projection: proj_base,
                     });
                     let pointer_type = source.describe_for_immutable_place();
@@ -136,11 +136,10 @@
                 }
             }
 
-            PlaceRef { base: PlaceBase::Static(_), .. }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::Index(_)] }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::ConstantIndex { .. }] }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::Subslice { .. }] }
-            | PlaceRef { base: _, projection: [.., ProjectionElem::Downcast(..)] } => {
+            PlaceRef { local: _, projection: [.., ProjectionElem::Index(_)] }
+            | PlaceRef { local: _, projection: [.., ProjectionElem::ConstantIndex { .. }] }
+            | PlaceRef { local: _, projection: [.., ProjectionElem::Subslice { .. }] }
+            | PlaceRef { local: _, projection: [.., ProjectionElem::Downcast(..)] } => {
                 bug!("Unexpected immutable place.")
             }
         }
@@ -188,7 +187,7 @@
             // struct we've got a field access of (it must be a reference since there's a deref
             // after the field access).
             PlaceRef {
-                base,
+                local,
                 projection:
                     [proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref],
             } => {
@@ -196,7 +195,7 @@
 
                 if let Some((span, message)) = annotate_struct_field(
                     self.infcx.tcx,
-                    Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty,
+                    Place::ty_from(local, proj_base, *self.body, self.infcx.tcx).ty,
                     field,
                 ) {
                     err.span_suggestion(
@@ -209,7 +208,7 @@
             }
 
             // Suggest removing a `&mut` from the use of a mutable reference.
-            PlaceRef { base: PlaceBase::Local(local), projection: [] }
+            PlaceRef { local, projection: [] }
                 if {
                     self.body
                         .local_decls
@@ -247,7 +246,7 @@
 
             // We want to suggest users use `let mut` for local (user
             // variable) mutations...
-            PlaceRef { base: PlaceBase::Local(local), projection: [] }
+            PlaceRef { local, projection: [] }
                 if self.body.local_decls[*local].can_be_made_mutable() =>
             {
                 // ... but it doesn't make sense to suggest it on
@@ -268,11 +267,11 @@
 
             // Also suggest adding mut for upvars
             PlaceRef {
-                base,
+                local,
                 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(local, proj_base, *self.body, self.infcx.tcx).ty
                 ));
 
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -299,7 +298,7 @@
             // complete hack to approximate old AST-borrowck
             // diagnostic: if the span starts with a mutable borrow of
             // a local variable, then just suggest the user remove it.
-            PlaceRef { base: PlaceBase::Local(_), projection: [] }
+            PlaceRef { local: _, projection: [] }
                 if {
                     if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         snippet.starts_with("&mut ")
@@ -312,7 +311,7 @@
                 err.span_label(span, "try removing `&mut` here");
             }
 
-            PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
                 if self.body.local_decls[*local].is_ref_for_guard() =>
             {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -326,7 +325,7 @@
             //
             // FIXME: can this case be generalized to work for an
             // arbitrary base for the projection?
-            PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref] }
+            PlaceRef { local, projection: [ProjectionElem::Deref] }
                 if self.body.local_decls[*local].is_user_variable() =>
             {
                 let local_decl = &self.body.local_decls[*local];
@@ -409,10 +408,10 @@
             }
 
             PlaceRef {
-                base,
+                local,
                 projection: [ProjectionElem::Deref],
                 // FIXME document what is this 1 magic number about
-            } if *base == PlaceBase::Local(Local::new(1)) && !self.upvars.is_empty() => {
+            } if *local == Local::new(1) && !self.upvars.is_empty() => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
                 err.span_help(
                     self.body.span,
@@ -420,7 +419,7 @@
                 );
             }
 
-            PlaceRef { base: _, projection: [.., ProjectionElem::Deref] } => {
+            PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
                 match opt_source {
diff --git a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
index 1425c22..ee94890 100644
--- a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
@@ -12,7 +12,7 @@
 
 use crate::borrow_check::MirBorrowckCtxt;
 
-use super::{ErrorConstraintInfo, RegionErrorNamingCtx, RegionName, RegionNameSource};
+use super::{ErrorConstraintInfo, RegionName, RegionNameSource};
 
 /// The different things we could suggest.
 enum SuggestedConstraint {
@@ -77,19 +77,15 @@
     fn region_vid_to_name(
         &self,
         mbcx: &MirBorrowckCtxt<'_, '_>,
-        renctx: &mut RegionErrorNamingCtx,
         region: RegionVid,
     ) -> Option<RegionName> {
-        mbcx.nonlexical_regioncx
-            .give_region_a_name(mbcx, renctx, region)
-            .filter(Self::region_name_is_suggestable)
+        mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
     }
 
     /// Compiles a list of all suggestions to be printed in the final big suggestion.
     fn compile_all_suggestions(
         &self,
         mbcx: &MirBorrowckCtxt<'_, '_>,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> SmallVec<[SuggestedConstraint; 2]> {
         let mut suggested = SmallVec::new();
 
@@ -98,7 +94,7 @@
         let mut unified_already = FxHashSet::default();
 
         for (fr, outlived) in &self.constraints_to_add {
-            let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, renctx, *fr) {
+            let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) {
                 fr_name
             } else {
                 continue;
@@ -107,9 +103,7 @@
             let outlived = outlived
                 .iter()
                 // if there is a `None`, we will just omit that constraint
-                .filter_map(|fr| {
-                    self.region_vid_to_name(mbcx, renctx, *fr).map(|rname| (fr, rname))
-                })
+                .filter_map(|fr| self.region_vid_to_name(mbcx, *fr).map(|rname| (fr, rname)))
                 .collect::<Vec<_>>();
 
             // No suggestable outlived lifetimes.
@@ -173,12 +167,11 @@
         &mut self,
         mbcx: &MirBorrowckCtxt<'_, '_>,
         errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
         // Emit an intermediate note.
-        let fr_name = self.region_vid_to_name(mbcx, renctx, errci.fr);
-        let outlived_fr_name = self.region_vid_to_name(mbcx, renctx, errci.outlived_fr);
+        let fr_name = self.region_vid_to_name(mbcx, errci.fr);
+        let outlived_fr_name = self.region_vid_to_name(mbcx, errci.outlived_fr);
 
         if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) {
             if let RegionNameSource::Static = outlived_fr_name.source {
@@ -194,11 +187,7 @@
 
     /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
     /// suggestion including all collected constraints.
-    crate fn add_suggestion(
-        &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_>,
-        renctx: &mut RegionErrorNamingCtx,
-    ) {
+    crate fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) {
         // No constraints to add? Done.
         if self.constraints_to_add.is_empty() {
             debug!("No constraints to suggest.");
@@ -215,7 +204,7 @@
         }
 
         // Get all suggestable constraints.
-        let suggested = self.compile_all_suggestions(mbcx, renctx);
+        let suggested = self.compile_all_suggestions(mbcx);
 
         // If there are no suggestable constraints...
         if suggested.is_empty() {
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 9a301a6..b999dfa 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -1,28 +1,25 @@
 //! Error reporting machinery for lifetime errors.
 
 use rustc::infer::{
-    error_reporting::nice_region_error::NiceRegionError, region_constraints::GenericKind,
-    InferCtxt, NLLRegionVariableOrigin,
+    error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin,
 };
-use rustc::mir::{Body, ConstraintCategory, Location};
+use rustc::mir::ConstraintCategory;
 use rustc::ty::{self, RegionVid, Ty};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::IndexVec;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
-use std::collections::VecDeque;
-use syntax::errors::Applicability;
 
 use crate::util::borrowck_errors;
 
 use crate::borrow_check::{
-    constraints::OutlivesConstraint, nll::ConstraintDescription,
-    region_infer::RegionInferenceContext, type_check::Locations, universal_regions::DefiningTy,
+    nll::ConstraintDescription,
+    region_infer::{values::RegionElement, TypeTest},
+    universal_regions::DefiningTy,
     MirBorrowckCtxt,
 };
 
-use super::{OutlivesSuggestionBuilder, RegionErrorNamingCtx, RegionName, RegionNameSource};
+use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
 
 impl ConstraintDescription for ConstraintCategory {
     fn description(&self) -> &'static str {
@@ -47,13 +44,6 @@
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum Trace {
-    StartRegion,
-    FromOutlivesConstraint(OutlivesConstraint),
-    NotVisited,
-}
-
 /// A collection of errors encountered during region inference. This is needed to efficiently
 /// report errors after borrow checking.
 ///
@@ -63,23 +53,8 @@
 
 #[derive(Clone, Debug)]
 crate enum RegionErrorKind<'tcx> {
-    /// An error for a type test: `T: 'a` does not live long enough.
-    TypeTestDoesNotLiveLongEnough {
-        /// The span of the type test.
-        span: Span,
-        /// The generic type of the type test.
-        generic: GenericKind<'tcx>,
-    },
-
-    /// A generic bound failure for a type test.
-    TypeTestGenericBoundError {
-        /// The span of the type test.
-        span: Span,
-        /// The generic type of the type test.
-        generic: GenericKind<'tcx>,
-        /// The lower bound region.
-        lower_bound_region: ty::Region<'tcx>,
-    },
+    /// A generic bound failure for a type test (`T: 'a`).
+    TypeTestError { type_test: TypeTest<'tcx> },
 
     /// An unexpected hidden region for an opaque type.
     UnexpectedHiddenRegion {
@@ -95,8 +70,8 @@
     BoundUniversalRegionError {
         /// The placeholder free region.
         longer_fr: RegionVid,
-        /// The region that erroneously must be outlived by `longer_fr`.
-        error_region: RegionVid,
+        /// The region element that erroneously must be outlived by `longer_fr`.
+        error_element: RegionElement,
         /// The origin of the placeholder region.
         fr_origin: NLLRegionVariableOrigin,
     },
@@ -129,26 +104,26 @@
     pub(super) span: Span,
 }
 
-impl<'tcx> RegionInferenceContext<'tcx> {
+impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// Converts a region inference variable into a `ty::Region` that
     /// we can use for error reporting. If `r` is universally bound,
     /// then we use the name that we have on record for it. If `r` is
     /// existentially bound, then we check its inferred value and try
     /// to find a good name from that. Returns `None` if we can't find
     /// one (e.g., this is just some random part of the CFG).
-    pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
-        self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
+    pub(super) fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
+        self.to_error_region_vid(r).and_then(|r| self.regioncx.region_definition(r).external_name)
     }
 
-    /// Returns the [RegionVid] corresponding to the region returned by
+    /// Returns the `RegionVid` corresponding to the region returned by
     /// `to_error_region`.
-    pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
-        if self.universal_regions.is_universal_region(r) {
+    pub(super) fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
+        if self.regioncx.universal_regions().is_universal_region(r) {
             Some(r)
         } else {
-            let r_scc = self.constraint_sccs.scc(r);
-            let upper_bound = self.universal_upper_bound(r);
-            if self.scc_values.contains(r_scc, upper_bound) {
+            let upper_bound = self.regioncx.universal_upper_bound(r);
+
+            if self.regioncx.upper_bound_in_region_scc(r, upper_bound) {
                 self.to_error_region_vid(upper_bound)
             } else {
                 None
@@ -156,270 +131,134 @@
         }
     }
 
-    /// Tries to find the best constraint to blame for the fact that
-    /// `R: from_region`, where `R` is some region that meets
-    /// `target_test`. This works by following the constraint graph,
-    /// creating a constraint path that forces `R` to outlive
-    /// `from_region`, and then finding the best choices within that
-    /// path to blame.
-    fn best_blame_constraint(
-        &self,
-        body: &Body<'tcx>,
-        from_region: RegionVid,
-        from_region_origin: NLLRegionVariableOrigin,
-        target_test: impl Fn(RegionVid) -> bool,
-    ) -> (ConstraintCategory, bool, Span) {
-        debug!(
-            "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
-            from_region, from_region_origin
-        );
-
-        // Find all paths
-        let (path, target_region) =
-            self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
-        debug!(
-            "best_blame_constraint: path={:#?}",
-            path.iter()
-                .map(|&c| format!(
-                    "{:?} ({:?}: {:?})",
-                    c,
-                    self.constraint_sccs.scc(c.sup),
-                    self.constraint_sccs.scc(c.sub),
-                ))
-                .collect::<Vec<_>>()
-        );
-
-        // Classify each of the constraints along the path.
-        let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
-            .iter()
-            .map(|constraint| {
-                if constraint.category == ConstraintCategory::ClosureBounds {
-                    self.retrieve_closure_constraint_info(body, &constraint)
-                } else {
-                    (constraint.category, false, constraint.locations.span(body))
-                }
-            })
-            .collect();
-        debug!("best_blame_constraint: categorized_path={:#?}", categorized_path);
-
-        // To find the best span to cite, we first try to look for the
-        // final constraint that is interesting and where the `sup` is
-        // not unified with the ultimate target region. The reason
-        // for this is that we have a chain of constraints that lead
-        // from the source to the target region, something like:
-        //
-        //    '0: '1 ('0 is the source)
-        //    '1: '2
-        //    '2: '3
-        //    '3: '4
-        //    '4: '5
-        //    '5: '6 ('6 is the target)
-        //
-        // Some of those regions are unified with `'6` (in the same
-        // SCC).  We want to screen those out. After that point, the
-        // "closest" constraint we have to the end is going to be the
-        // most likely to be the point where the value escapes -- but
-        // we still want to screen for an "interesting" point to
-        // highlight (e.g., a call site or something).
-        let target_scc = self.constraint_sccs.scc(target_region);
-        let mut range = 0..path.len();
-
-        // As noted above, when reporting an error, there is typically a chain of constraints
-        // leading from some "source" region which must outlive some "target" region.
-        // In most cases, we prefer to "blame" the constraints closer to the target --
-        // but there is one exception. When constraints arise from higher-ranked subtyping,
-        // we generally prefer to blame the source value,
-        // as the "target" in this case tends to be some type annotation that the user gave.
-        // Therefore, if we find that the region origin is some instantiation
-        // of a higher-ranked region, we start our search from the "source" point
-        // rather than the "target", and we also tweak a few other things.
-        //
-        // An example might be this bit of Rust code:
-        //
-        // ```rust
-        // let x: fn(&'static ()) = |_| {};
-        // let y: for<'a> fn(&'a ()) = x;
-        // ```
-        //
-        // In MIR, this will be converted into a combination of assignments and type ascriptions.
-        // In particular, the 'static is imposed through a type ascription:
-        //
-        // ```rust
-        // x = ...;
-        // AscribeUserType(x, fn(&'static ())
-        // y = x;
-        // ```
-        //
-        // We wind up ultimately with constraints like
-        //
-        // ```rust
-        // !a: 'temp1 // from the `y = x` statement
-        // 'temp1: 'temp2
-        // 'temp2: 'static // from the AscribeUserType
-        // ```
-        //
-        // and here we prefer to blame the source (the y = x statement).
-        let blame_source = match from_region_origin {
-            NLLRegionVariableOrigin::FreeRegion
-            | NLLRegionVariableOrigin::Existential { from_forall: false } => true,
-            NLLRegionVariableOrigin::Placeholder(_)
-            | NLLRegionVariableOrigin::Existential { from_forall: true } => false,
-        };
-
-        let find_region = |i: &usize| {
-            let constraint = path[*i];
-
-            let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
-
-            if blame_source {
-                match categorized_path[*i].0 {
-                    ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal => false,
-                    ConstraintCategory::TypeAnnotation
-                    | ConstraintCategory::Return
-                    | ConstraintCategory::Yield => true,
-                    _ => constraint_sup_scc != target_scc,
-                }
-            } else {
-                match categorized_path[*i].0 {
-                    ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal => false,
-                    _ => true,
-                }
-            }
-        };
-
-        let best_choice =
-            if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
-
-        debug!(
-            "best_blame_constraint: best_choice={:?} blame_source={}",
-            best_choice, blame_source
-        );
-
-        if let Some(i) = best_choice {
-            if let Some(next) = categorized_path.get(i + 1) {
-                if categorized_path[i].0 == ConstraintCategory::Return
-                    && next.0 == ConstraintCategory::OpaqueType
+    /// Returns `true` if a closure is inferred to be an `FnMut` closure.
+    fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
+        if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
+            if let ty::BoundRegion::BrEnv = free_region.bound_region {
+                if let DefiningTy::Closure(def_id, substs) =
+                    self.regioncx.universal_regions().defining_ty
                 {
-                    // The return expression is being influenced by the return type being
-                    // impl Trait, point at the return type and not the return expr.
-                    return *next;
+                    return substs.as_closure().kind(def_id, self.infcx.tcx)
+                        == ty::ClosureKind::FnMut;
                 }
             }
-            return categorized_path[i];
         }
 
-        // If that search fails, that is.. unusual. Maybe everything
-        // is in the same SCC or something. In that case, find what
-        // appears to be the most interesting point to report to the
-        // user via an even more ad-hoc guess.
-        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
-        debug!("`: sorted_path={:#?}", categorized_path);
-
-        *categorized_path.first().unwrap()
+        false
     }
 
-    /// Walks the graph of constraints (where `'a: 'b` is considered
-    /// an edge `'a -> 'b`) to find all paths from `from_region` to
-    /// `to_region`. The paths are accumulated into the vector
-    /// `results`. The paths are stored as a series of
-    /// `ConstraintIndex` values -- in other words, a list of *edges*.
-    ///
-    /// Returns: a series of constraints as well as the region `R`
-    /// that passed the target test.
-    fn find_constraint_paths_between_regions(
-        &self,
-        from_region: RegionVid,
-        target_test: impl Fn(RegionVid) -> bool,
-    ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
-        let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
-        context[from_region] = Trace::StartRegion;
+    /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
+    pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
+        // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
+        // buffered in the `MirBorrowckCtxt`.
 
-        // Use a deque so that we do a breadth-first search. We will
-        // stop at the first match, which ought to be the shortest
-        // path (fewest constraints).
-        let mut deque = VecDeque::new();
-        deque.push_back(from_region);
+        let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
 
-        while let Some(r) = deque.pop_front() {
-            debug!(
-                "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
-                from_region,
-                r,
-                self.region_value_str(r),
-            );
+        for nll_error in nll_errors.into_iter() {
+            match nll_error {
+                RegionErrorKind::TypeTestError { type_test } => {
+                    // Try to convert the lower-bound region into something named we can print for the user.
+                    let lower_bound_region = self.to_error_region(type_test.lower_bound);
 
-            // Check if we reached the region we were looking for. If so,
-            // we can reconstruct the path that led to it and return it.
-            if target_test(r) {
-                let mut result = vec![];
-                let mut p = r;
-                loop {
-                    match context[p] {
-                        Trace::NotVisited => {
-                            bug!("found unvisited region {:?} on path to {:?}", p, r)
-                        }
+                    let type_test_span = type_test.locations.span(&self.body);
 
-                        Trace::FromOutlivesConstraint(c) => {
-                            result.push(c);
-                            p = c.sup;
-                        }
+                    if let Some(lower_bound_region) = lower_bound_region {
+                        let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
+                        self.infcx
+                            .construct_generic_bound_failure(
+                                region_scope_tree,
+                                type_test_span,
+                                None,
+                                type_test.generic_kind,
+                                lower_bound_region,
+                            )
+                            .buffer(&mut self.errors_buffer);
+                    } else {
+                        // FIXME. We should handle this case better. It
+                        // indicates that we have e.g., some region variable
+                        // whose value is like `'a+'b` where `'a` and `'b` are
+                        // distinct unrelated univesal regions that are not
+                        // known to outlive one another. It'd be nice to have
+                        // some examples where this arises to decide how best
+                        // to report it; we could probably handle it by
+                        // iterating over the universal regions and reporting
+                        // an error that multiple bounds are required.
+                        self.infcx
+                            .tcx
+                            .sess
+                            .struct_span_err(
+                                type_test_span,
+                                &format!("`{}` does not live long enough", type_test.generic_kind),
+                            )
+                            .buffer(&mut self.errors_buffer);
+                    }
+                }
 
-                        Trace::StartRegion => {
-                            result.reverse();
-                            return Some((result, r));
-                        }
+                RegionErrorKind::UnexpectedHiddenRegion {
+                    opaque_type_def_id,
+                    hidden_ty,
+                    member_region,
+                } => {
+                    let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
+                    opaque_types::unexpected_hidden_region_diagnostic(
+                        self.infcx.tcx,
+                        Some(region_scope_tree),
+                        opaque_type_def_id,
+                        hidden_ty,
+                        member_region,
+                    )
+                    .buffer(&mut self.errors_buffer);
+                }
+
+                RegionErrorKind::BoundUniversalRegionError {
+                    longer_fr,
+                    fr_origin,
+                    error_element,
+                } => {
+                    let error_region = self.regioncx.region_from_element(longer_fr, error_element);
+
+                    // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
+                    let (_, span) = self.regioncx.find_outlives_blame_span(
+                        &self.body,
+                        longer_fr,
+                        fr_origin,
+                        error_region,
+                    );
+
+                    // FIXME: improve this error message
+                    self.infcx
+                        .tcx
+                        .sess
+                        .struct_span_err(span, "higher-ranked subtype error")
+                        .buffer(&mut self.errors_buffer);
+                }
+
+                RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
+                    if is_reported {
+                        self.report_region_error(
+                            longer_fr,
+                            fr_origin,
+                            shorter_fr,
+                            &mut outlives_suggestion,
+                        );
+                    } else {
+                        // We only report the first error, so as not to overwhelm the user. See
+                        // `RegRegionErrorKind` docs.
+                        //
+                        // FIXME: currently we do nothing with these, but perhaps we can do better?
+                        // FIXME: try collecting these constraints on the outlives suggestion
+                        // builder. Does it make the suggestions any better?
+                        debug!(
+                            "Unreported region error: can't prove that {:?}: {:?}",
+                            longer_fr, shorter_fr
+                        );
                     }
                 }
             }
-
-            // Otherwise, walk over the outgoing constraints and
-            // enqueue any regions we find, keeping track of how we
-            // reached them.
-
-            // A constraint like `'r: 'x` can come from our constraint
-            // graph.
-            let fr_static = self.universal_regions.fr_static;
-            let outgoing_edges_from_graph =
-                self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
-
-            // Always inline this closure because it can be hot.
-            let mut handle_constraint = #[inline(always)]
-            |constraint: OutlivesConstraint| {
-                debug_assert_eq!(constraint.sup, r);
-                let sub_region = constraint.sub;
-                if let Trace::NotVisited = context[sub_region] {
-                    context[sub_region] = Trace::FromOutlivesConstraint(constraint);
-                    deque.push_back(sub_region);
-                }
-            };
-
-            // This loop can be hot.
-            for constraint in outgoing_edges_from_graph {
-                handle_constraint(constraint);
-            }
-
-            // Member constraints can also give rise to `'r: 'x` edges that
-            // were not part of the graph initially, so watch out for those.
-            // (But they are extremely rare; this loop is very cold.)
-            for constraint in self.applied_member_constraints(r) {
-                let p_c = &self.member_constraints[constraint.member_constraint_index];
-                let constraint = OutlivesConstraint {
-                    sup: r,
-                    sub: constraint.min_choice,
-                    locations: Locations::All(p_c.definition_span),
-                    category: ConstraintCategory::OpaqueType,
-                };
-                handle_constraint(constraint);
-            }
         }
 
-        None
+        // Emit one outlives suggestions for each MIR def we borrowck
+        outlives_suggestion.add_suggestion(self);
     }
 
     /// Report an error because the universal region `fr` was required to outlive
@@ -430,38 +269,38 @@
     /// ```
     ///
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
-    pub(in crate::borrow_check) fn report_error<'a>(
-        &'a self,
-        mbcx: &MirBorrowckCtxt<'a, 'tcx>,
+    pub(in crate::borrow_check) fn report_region_error(
+        &mut self,
         fr: RegionVid,
         fr_origin: NLLRegionVariableOrigin,
         outlived_fr: RegionVid,
         outlives_suggestion: &mut OutlivesSuggestionBuilder,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'a> {
-        debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
+    ) {
+        debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (category, _, span) = self.best_blame_constraint(&mbcx.body, fr, fr_origin, |r| {
-            self.provides_universal_region(r, fr, outlived_fr)
-        });
+        let (category, _, span) =
+            self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
+                self.regioncx.provides_universal_region(r, fr, outlived_fr)
+            });
 
-        debug!("report_error: category={:?} {:?}", category, span);
+        debug!("report_region_error: category={:?} {:?}", category, span);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
-            let tables = mbcx.infcx.tcx.typeck_tables_of(mbcx.mir_def_id);
-            let nice = NiceRegionError::new_from_span(mbcx.infcx, span, o, f, Some(tables));
+            let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id);
+            let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables));
             if let Some(diag) = nice.try_report_from_nll() {
-                return diag;
+                diag.buffer(&mut self.errors_buffer);
+                return;
             }
         }
 
         let (fr_is_local, outlived_fr_is_local): (bool, bool) = (
-            self.universal_regions.is_local_free_region(fr),
-            self.universal_regions.is_local_free_region(outlived_fr),
+            self.regioncx.universal_regions().is_local_free_region(fr),
+            self.regioncx.universal_regions().is_local_free_region(outlived_fr),
         );
 
         debug!(
-            "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
+            "report_region_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
             fr_is_local, outlived_fr_is_local, category
         );
 
@@ -474,52 +313,30 @@
             span,
         };
 
-        match (category, fr_is_local, outlived_fr_is_local) {
-            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(mbcx.infcx, fr) => {
-                self.report_fnmut_error(mbcx, &errci, renctx)
+        let diag = match (category, fr_is_local, outlived_fr_is_local) {
+            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(fr) => {
+                self.report_fnmut_error(&errci)
             }
             (ConstraintCategory::Assignment, true, false)
             | (ConstraintCategory::CallArgument, true, false) => {
-                let mut db = self.report_escaping_data_error(mbcx, &errci, renctx);
+                let mut db = self.report_escaping_data_error(&errci);
 
-                outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
+                outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
                 outlives_suggestion.collect_constraint(fr, outlived_fr);
 
                 db
             }
             _ => {
-                let mut db = self.report_general_error(mbcx, &errci, renctx);
+                let mut db = self.report_general_error(&errci);
 
-                outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
+                outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
                 outlives_suggestion.collect_constraint(fr, outlived_fr);
 
                 db
             }
-        }
-    }
-
-    /// We have a constraint `fr1: fr2` that is not satisfied, where
-    /// `fr2` represents some universal region. Here, `r` is some
-    /// region where we know that `fr1: r` and this function has the
-    /// job of determining whether `r` is "to blame" for the fact that
-    /// `fr1: fr2` is required.
-    ///
-    /// This is true under two conditions:
-    ///
-    /// - `r == fr2`
-    /// - `fr2` is `'static` and `r` is some placeholder in a universe
-    ///   that cannot be named by `fr1`; in that case, we will require
-    ///   that `fr1: 'static` because it is the only way to `fr1: r` to
-    ///   be satisfied. (See `add_incompatible_universe`.)
-    fn provides_universal_region(&self, r: RegionVid, fr1: RegionVid, fr2: RegionVid) -> bool {
-        debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
-        let result = {
-            r == fr2 || {
-                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
-            }
         };
-        debug!("provides_universal_region: result = {:?}", result);
-        result
+
+        diag.buffer(&mut self.errors_buffer);
     }
 
     /// Report a specialized error when `FnMut` closures return a reference to a captured variable.
@@ -538,15 +355,10 @@
     ///            executing...
     ///    = note: ...therefore, returned references to captured variables will escape the closure
     /// ```
-    fn report_fnmut_error(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'_> {
+    fn report_fnmut_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
-        let mut diag = mbcx
+        let mut diag = self
             .infcx
             .tcx
             .sess
@@ -554,7 +366,8 @@
 
         // 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.
-        let return_type_is_closure = self.universal_regions.unnormalized_output_ty.is_closure();
+        let return_type_is_closure =
+            self.regioncx.universal_regions().unnormalized_output_ty.is_closure();
         let message = if return_type_is_closure {
             "returns a closure that contains a reference to a captured variable, which then \
              escapes the closure body"
@@ -564,7 +377,7 @@
 
         diag.span_label(*span, message);
 
-        match self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap().source {
+        match self.give_region_a_name(*outlived_fr).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -599,30 +412,25 @@
     /// LL |     ref_obj(x)
     ///    |     ^^^^^^^^^^ `x` escapes the function body here
     /// ```
-    fn report_escaping_data_error(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'_> {
+    fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo { span, category, .. } = errci;
 
-        let fr_name_and_span = self.get_var_name_and_span_for_region(
-            mbcx.infcx.tcx,
-            &mbcx.body,
-            &mbcx.local_names,
-            &mbcx.upvars,
+        let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
+            self.infcx.tcx,
+            &self.body,
+            &self.local_names,
+            &self.upvars,
             errci.fr,
         );
-        let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(
-            mbcx.infcx.tcx,
-            &mbcx.body,
-            &mbcx.local_names,
-            &mbcx.upvars,
+        let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
+            self.infcx.tcx,
+            &self.body,
+            &self.local_names,
+            &self.upvars,
             errci.outlived_fr,
         );
 
-        let escapes_from = match self.universal_regions.defining_ty {
+        let escapes_from = match self.regioncx.universal_regions().defining_ty {
             DefiningTy::Closure(..) => "closure",
             DefiningTy::Generator(..) => "generator",
             DefiningTy::FnDef(..) => "function",
@@ -635,15 +443,15 @@
             || (*category == ConstraintCategory::Assignment && escapes_from == "function")
             || escapes_from == "const"
         {
-            return self.report_general_error(
-                mbcx,
-                &ErrorConstraintInfo { fr_is_local: true, outlived_fr_is_local: false, ..*errci },
-                renctx,
-            );
+            return self.report_general_error(&ErrorConstraintInfo {
+                fr_is_local: true,
+                outlived_fr_is_local: false,
+                ..*errci
+            });
         }
 
         let mut diag =
-            borrowck_errors::borrowed_data_escapes_closure(mbcx.infcx.tcx, *span, escapes_from);
+            borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from);
 
         if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
             diag.span_label(
@@ -685,12 +493,7 @@
     ///    |     ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
     ///    |                    is returning data with lifetime `'b`
     /// ```
-    fn report_general_error(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'_> {
+    fn report_general_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo {
             fr,
             fr_is_local,
@@ -702,14 +505,14 @@
         } = errci;
 
         let mut diag =
-            mbcx.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
+            self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
 
         let mir_def_name =
-            if mbcx.infcx.tcx.is_closure(mbcx.mir_def_id) { "closure" } else { "function" };
+            if self.infcx.tcx.is_closure(self.mir_def_id) { "closure" } else { "function" };
 
-        let fr_name = self.give_region_a_name(mbcx, renctx, *fr).unwrap();
+        let fr_name = self.give_region_a_name(*fr).unwrap();
         fr_name.highlight_region_name(&mut diag);
-        let outlived_fr_name = self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap();
+        let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
         outlived_fr_name.highlight_region_name(&mut diag);
 
         match (category, outlived_fr_is_local, fr_is_local) {
@@ -736,7 +539,7 @@
             }
         }
 
-        self.add_static_impl_trait_suggestion(mbcx.infcx, &mut diag, *fr, fr_name, *outlived_fr);
+        self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
 
         diag
     }
@@ -752,8 +555,7 @@
     /// ```
     fn add_static_impl_trait_suggestion(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        diag: &mut DiagnosticBuilder<'_>,
+        diag: &mut DiagnosticBuilder<'tcx>,
         fr: RegionVid,
         // We need to pass `fr_name` - computing it again will label it twice.
         fr_name: RegionName,
@@ -762,11 +564,12 @@
         if let (Some(f), Some(ty::RegionKind::ReStatic)) =
             (self.to_error_region(fr), self.to_error_region(outlived_fr))
         {
-            if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. }, _)) = infcx
+            if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. }, _)) = self
+                .infcx
                 .tcx
                 .is_suitable_region(f)
                 .map(|r| r.def_id)
-                .map(|id| infcx.tcx.return_type_impl_trait(id))
+                .map(|id| self.infcx.tcx.return_type_impl_trait(id))
                 .unwrap_or(None)
             {
                 // Check whether or not the impl trait return type is intended to capture
@@ -774,8 +577,8 @@
                 //
                 // eg. check for `impl Trait + 'static` instead of `impl Trait`.
                 let has_static_predicate = {
-                    let predicates_of = infcx.tcx.predicates_of(*did);
-                    let bounds = predicates_of.instantiate(infcx.tcx, substs);
+                    let predicates_of = self.infcx.tcx.predicates_of(*did);
+                    let bounds = predicates_of.instantiate(self.infcx.tcx, substs);
 
                     let mut found = false;
                     for predicate in bounds.predicates {
@@ -803,8 +606,8 @@
                     diag.help(&format!("consider replacing `{}` with `{}`", fr_name, static_str));
                 } else {
                     // Otherwise, we should suggest adding a constraint on the return type.
-                    let span = infcx.tcx.def_span(*did);
-                    if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
+                    let span = self.infcx.tcx.def_span(*did);
+                    if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         let suggestable_fr_name = if fr_name.was_named() {
                             fr_name.to_string()
                         } else {
@@ -831,130 +634,4 @@
             }
         }
     }
-
-    crate fn free_region_constraint_info(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        borrow_region: RegionVid,
-        outlived_region: RegionVid,
-    ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
-        let (category, from_closure, span) = self.best_blame_constraint(
-            &mbcx.body,
-            borrow_region,
-            NLLRegionVariableOrigin::FreeRegion,
-            |r| self.provides_universal_region(r, borrow_region, outlived_region),
-        );
-
-        let mut renctx = RegionErrorNamingCtx::new();
-        let outlived_fr_name = self.give_region_a_name(mbcx, &mut renctx, outlived_region);
-
-        (category, from_closure, span, outlived_fr_name)
-    }
-
-    // Finds some region R such that `fr1: R` and `R` is live at
-    // `elem`.
-    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
-        debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
-        self.find_constraint_paths_between_regions(fr1, |r| {
-            // First look for some `r` such that `fr1: r` and `r` is live at `elem`
-            debug!(
-                "find_sub_region_live_at: liveness_constraints for {:?} are {:?}",
-                r,
-                self.liveness_constraints.region_value_str(r),
-            );
-            self.liveness_constraints.contains(r, elem)
-        })
-        .or_else(|| {
-            // If we fail to find that, we may find some `r` such that
-            // `fr1: r` and `r` is a placeholder from some universe
-            // `fr1` cannot name. This would force `fr1` to be
-            // `'static`.
-            self.find_constraint_paths_between_regions(fr1, |r| {
-                self.cannot_name_placeholder(fr1, r)
-            })
-        })
-        .or_else(|| {
-            // If we fail to find THAT, it may be that `fr1` is a
-            // placeholder that cannot "fit" into its SCC. In that
-            // case, there should be some `r` where `fr1: r`, both
-            // `fr1` and `r` are in the same SCC, and `fr1` is a
-            // placeholder that `r` cannot name. We can blame that
-            // edge.
-            self.find_constraint_paths_between_regions(fr1, |r| {
-                self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r)
-                    && self.cannot_name_placeholder(r, fr1)
-            })
-        })
-        .map(|(_path, r)| r)
-        .unwrap()
-    }
-
-    // Finds a good span to blame for the fact that `fr1` outlives `fr2`.
-    crate fn find_outlives_blame_span(
-        &self,
-        body: &Body<'tcx>,
-        fr1: RegionVid,
-        fr1_origin: NLLRegionVariableOrigin,
-        fr2: RegionVid,
-    ) -> (ConstraintCategory, Span) {
-        let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| {
-            self.provides_universal_region(r, fr1, fr2)
-        });
-        (category, span)
-    }
-
-    fn retrieve_closure_constraint_info(
-        &self,
-        body: &Body<'tcx>,
-        constraint: &OutlivesConstraint,
-    ) -> (ConstraintCategory, bool, Span) {
-        let loc = match constraint.locations {
-            Locations::All(span) => return (constraint.category, false, span),
-            Locations::Single(loc) => loc,
-        };
-
-        let opt_span_category =
-            self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
-        opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or((
-            constraint.category,
-            false,
-            body.source_info(loc).span,
-        ))
-    }
-
-    /// Returns `true` if a closure is inferred to be an `FnMut` closure.
-    crate fn is_closure_fn_mut(&self, infcx: &InferCtxt<'_, 'tcx>, fr: RegionVid) -> bool {
-        if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
-            if let ty::BoundRegion::BrEnv = free_region.bound_region {
-                if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty {
-                    let closure_kind_ty = substs.as_closure().kind_ty(def_id, infcx.tcx);
-                    return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind();
-                }
-            }
-        }
-
-        false
-    }
-
-    /// If `r2` represents a placeholder region, then this returns
-    /// `true` if `r1` cannot name that placeholder in its
-    /// value; otherwise, returns `false`.
-    fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
-        debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2);
-
-        match self.definitions[r2].origin {
-            NLLRegionVariableOrigin::Placeholder(placeholder) => {
-                let universe1 = self.definitions[r1].universe;
-                debug!(
-                    "cannot_name_value_of: universe1={:?} placeholder={:?}",
-                    universe1, placeholder
-                );
-                universe1.cannot_name(placeholder.universe)
-            }
-
-            NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => {
-                false
-            }
-        }
-    }
 }
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
index 734e386..47eb2d8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -2,18 +2,14 @@
 
 use rustc::ty::print::RegionHighlightMode;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
-use rustc::ty::{self, RegionVid, Ty, TyCtxt};
-use rustc_data_structures::fx::FxHashMap;
+use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_span::symbol::kw;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
 
-use crate::borrow_check::{
-    nll::ToRegionVid, region_infer::RegionInferenceContext, universal_regions::DefiningTy,
-    MirBorrowckCtxt,
-};
+use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
 
 /// 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`.
@@ -55,46 +51,6 @@
     AnonRegionFromAsyncFn(Span),
 }
 
-/// 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() }
-    }
-
-    /// Get the name of `region` if it has previously been named.
-    crate fn get(&self, region: &RegionVid) -> Option<&RegionName> {
-        self.renctx.get(region)
-    }
-
-    /// Give `region` the name `name`.
-    crate fn insert(&mut self, region: RegionVid, name: RegionName) {
-        self.renctx.insert(region, name);
-    }
-
-    /// Creates a synthetic region named `'N`, where `N` is the next value of the counter. Then,
-    /// increment the counter.
-    ///
-    /// The name is not memoized. A separate call to `insert` should be made later. (Currently,
-    /// this happens at the end of `give_region_a_name`).
-    crate fn synthesize_region_name(&mut self) -> Symbol {
-        let c = self.counter;
-        self.counter += 1;
-
-        Symbol::intern(&format!("'{:?}", c))
-    }
-}
-
 impl RegionName {
     crate fn was_named(&self) -> bool {
         match self.source {
@@ -161,7 +117,16 @@
     }
 }
 
-impl<'tcx> RegionInferenceContext<'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
+    /// Generate a synthetic region named `'N`, where `N` is the next value of the counter. Then,
+    /// increment the counter.
+    ///
+    /// This is _not_ idempotent. Call `give_region_a_name` when possible.
+    fn synthesize_region_name(&self) -> Symbol {
+        let c = self.next_region_name.replace_with(|counter| *counter + 1);
+        Symbol::intern(&format!("'{:?}", c))
+    }
+
     /// Maps from an internal MIR region vid to something that we can
     /// report to the user. In some cases, the region vids will map
     /// directly to lifetimes that the user has a name for (e.g.,
@@ -170,6 +135,8 @@
     /// that end, this function takes a "diagnostic" so that it can
     /// create auxiliary notes as needed.
     ///
+    /// The names are memoized, so this is both cheap to recompute and idempotent.
+    ///
     /// Example (function arguments):
     ///
     /// Suppose we are trying to give a name to the lifetime of the
@@ -187,29 +154,28 @@
     /// ```
     ///
     /// and then return the name `'1` for us to use.
-    crate fn give_region_a_name(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        renctx: &mut RegionErrorNamingCtx,
-        fr: RegionVid,
-    ) -> Option<RegionName> {
-        debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
+    crate fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
+        debug!(
+            "give_region_a_name(fr={:?}, counter={:?})",
+            fr,
+            self.next_region_name.try_borrow().unwrap()
+        );
 
-        assert!(self.universal_regions.is_universal_region(fr));
+        assert!(self.regioncx.universal_regions().is_universal_region(fr));
 
-        if let Some(value) = renctx.get(&fr) {
+        if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) {
             return Some(value.clone());
         }
 
         let value = self
-            .give_name_from_error_region(mbcx, fr, renctx)
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(mbcx, fr, renctx))
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(mbcx, fr, renctx))
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_output(mbcx, fr, renctx))
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(mbcx, fr, renctx));
+            .give_name_from_error_region(fr)
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr));
 
         if let Some(ref value) = value {
-            renctx.insert(fr, value.clone());
+            self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
         }
 
         debug!("give_region_a_name: gave name {:?}", value);
@@ -220,15 +186,10 @@
     /// *user* has a name for. In that case, we'll be able to map
     /// `fr` to a `Region<'tcx>`, and that region will be one of
     /// named variants.
-    fn give_name_from_error_region(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> Option<RegionName> {
+    fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
-        let tcx = mbcx.infcx.tcx;
+        let tcx = self.infcx.tcx;
 
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match error_region {
@@ -267,7 +228,7 @@
                         // happen if we have an elided name in an async fn for example: the
                         // compiler will generate a region named `'_`, but reporting such a name is
                         // not actually useful, so we synthesize a name for it instead.
-                        let name = renctx.synthesize_region_name();
+                        let name = self.synthesize_region_name();
                         Some(RegionName {
                             name,
                             source: RegionNameSource::AnonRegionFromAsyncFn(span),
@@ -276,13 +237,13 @@
                 }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id = mbcx
+                    let mir_hir_id = self
                         .infcx
                         .tcx
                         .hir()
-                        .as_local_hir_id(mbcx.mir_def_id)
+                        .as_local_hir_id(self.mir_def_id)
                         .expect("non-local mir");
-                    let def_ty = self.universal_regions.defining_ty;
+                    let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     if let DefiningTy::Closure(def_id, substs) = def_ty {
                         let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) =
@@ -292,7 +253,7 @@
                         } else {
                             bug!("Closure is not defined by a closure expr");
                         };
-                        let region_name = renctx.synthesize_region_name();
+                        let region_name = self.synthesize_region_name();
 
                         let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx);
                         let note = match closure_kind_ty.to_opt_closure_kind() {
@@ -346,38 +307,30 @@
     /// ```
     fn give_name_if_anonymous_region_appears_in_arguments(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
-        let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, fr)?;
+        let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs();
+        let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?;
 
-        let arg_ty =
-            self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index];
-        if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(
-            mbcx,
-            fr,
-            arg_ty,
-            argument_index,
-            renctx,
-        ) {
+        let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys
+            [implicit_inputs + argument_index];
+        if let Some(region_name) =
+            self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index)
+        {
             return Some(region_name);
         }
 
-        self.give_name_if_we_cannot_match_hir_ty(mbcx, fr, arg_ty, renctx)
+        self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty)
     }
 
     fn give_name_if_we_can_match_hir_ty_from_argument(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_index: usize,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let mir_hir_id = mbcx.infcx.tcx.hir().as_local_hir_id(mbcx.mir_def_id)?;
-        let fn_decl = mbcx.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
+        let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id)?;
+        let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
         let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
         match argument_hir_ty.kind {
             // This indicates a variable with no type annotation, like
@@ -387,13 +340,7 @@
             // (`give_name_if_anonymous_region_appears_in_arguments`).
             hir::TyKind::Infer => None,
 
-            _ => self.give_name_if_we_can_match_hir_ty(
-                mbcx.infcx.tcx,
-                needle_fr,
-                argument_ty,
-                argument_hir_ty,
-                renctx,
-            ),
+            _ => self.give_name_if_we_can_match_hir_ty(needle_fr, argument_ty, argument_hir_ty),
         }
     }
 
@@ -410,15 +357,13 @@
     /// ```
     fn give_name_if_we_cannot_match_hir_ty(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let counter = renctx.counter;
+        let counter = *self.next_region_name.try_borrow().unwrap();
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(needle_fr, counter);
-        let type_name = mbcx.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
+        let type_name = self.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
 
         debug!(
             "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -426,10 +371,11 @@
         );
         let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
             // Only add a label if we can confirm that a region was labelled.
-            let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, needle_fr)?;
-            let (_, span) = self.get_argument_name_and_span_for_region(
-                &mbcx.body,
-                &mbcx.local_names,
+            let argument_index =
+                self.regioncx.get_argument_index_for_region(self.infcx.tcx, needle_fr)?;
+            let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
+                &self.body,
+                &self.local_names,
                 argument_index,
             );
 
@@ -437,7 +383,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: renctx.synthesize_region_name(),
+                name: self.synthesize_region_name(),
                 source: RegionNameSource::CannotMatchHirTy(span, type_name),
             })
         } else {
@@ -470,11 +416,9 @@
     /// to highlighting that closest type instead.
     fn give_name_if_we_can_match_hir_ty(
         &self,
-        tcx: TyCtxt<'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_hir_ty: &hir::Ty<'_>,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> =
             &mut vec![(argument_ty, argument_hir_ty)];
@@ -492,10 +436,10 @@
                     hir::TyKind::Rptr(_lifetime, referent_hir_ty),
                 ) => {
                     if region.to_region_vid() == needle_fr {
-                        let region_name = renctx.synthesize_region_name();
+                        let region_name = self.synthesize_region_name();
 
                         // Just grab the first character, the `&`.
-                        let source_map = tcx.sess.source_map();
+                        let source_map = self.infcx.tcx.sess.source_map();
                         let ampersand_span = source_map.start_point(hir_ty.span);
 
                         return Some(RegionName {
@@ -525,7 +469,6 @@
                                     substs,
                                     needle_fr,
                                     last_segment,
-                                    renctx,
                                     search_stack,
                                 ) {
                                     return Some(name);
@@ -570,7 +513,6 @@
         substs: SubstsRef<'tcx>,
         needle_fr: RegionVid,
         last_segment: &'hir hir::PathSegment<'hir>,
-        renctx: &mut RegionErrorNamingCtx,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
     ) -> Option<RegionName> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
@@ -582,7 +524,7 @@
             | hir::LifetimeName::Error
             | hir::LifetimeName::Static
             | hir::LifetimeName::Underscore => {
-                let region_name = renctx.synthesize_region_name();
+                let region_name = self.synthesize_region_name();
                 let ampersand_span = lifetime.span;
                 Some(RegionName {
                     name: region_name,
@@ -663,16 +605,14 @@
     ///  | let x = Some(&22);
     ///        - fully elaborated type of `x` is `Option<&'1 u32>`
     /// ```
-    fn give_name_if_anonymous_region_appears_in_upvars(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> Option<RegionName> {
-        let upvar_index = self.get_upvar_index_for_region(mbcx.infcx.tcx, fr)?;
-        let (upvar_name, upvar_span) =
-            self.get_upvar_name_and_span_for_region(mbcx.infcx.tcx, &mbcx.upvars, upvar_index);
-        let region_name = renctx.synthesize_region_name();
+    fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
+        let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
+        let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
+            self.infcx.tcx,
+            &self.upvars,
+            upvar_index,
+        );
+        let region_name = self.synthesize_region_name();
 
         Some(RegionName {
             name: region_name,
@@ -684,25 +624,20 @@
     /// must be a closure since, in a free fn, such an argument would
     /// have to either also appear in an argument (if using elision)
     /// or be early bound (named, not in argument).
-    fn give_name_if_anonymous_region_appears_in_output(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> Option<RegionName> {
-        let tcx = mbcx.infcx.tcx;
+    fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
+        let tcx = self.infcx.tcx;
 
-        let return_ty = self.universal_regions.unnormalized_output_ty;
+        let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
         debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
         if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) {
             return None;
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, renctx.counter);
-        let type_name = mbcx.infcx.extract_type_name(&return_ty, Some(highlight)).0;
+        highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
+        let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");
+        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir");
 
         let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
@@ -719,14 +654,14 @@
                 kind: hir::ImplItemKind::Method(method_sig, _),
                 ..
             }) => (method_sig.decl.output.span(), ""),
-            _ => (mbcx.body.span, ""),
+            _ => (self.body.span, ""),
         };
 
         Some(RegionName {
             // 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: renctx.synthesize_region_name(),
+            name: self.synthesize_region_name(),
             source: RegionNameSource::AnonRegionFromOutput(
                 return_span,
                 mir_description.to_string(),
@@ -737,32 +672,30 @@
 
     fn give_name_if_anonymous_region_appears_in_yield_ty(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         // Note: generators from `async fn` yield `()`, so we don't have to
         // worry about them here.
-        let yield_ty = self.universal_regions.yield_ty?;
+        let yield_ty = self.regioncx.universal_regions().yield_ty?;
         debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,);
 
-        let tcx = mbcx.infcx.tcx;
+        let tcx = self.infcx.tcx;
 
         if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) {
             return None;
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, renctx.counter);
-        let type_name = mbcx.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
+        highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
+        let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");
+        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir");
 
         let yield_span = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
                 kind: hir::ExprKind::Closure(_, _, _, span, _), ..
             }) => (tcx.sess.source_map().end_point(*span)),
-            _ => mbcx.body.span,
+            _ => self.body.span,
         };
 
         debug!(
@@ -772,7 +705,7 @@
         );
 
         Some(RegionName {
-            name: renctx.synthesize_region_name(),
+            name: self.synthesize_region_name(),
             source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
         })
     }
diff --git a/src/librustc_mir/borrow_check/diagnostics/var_name.rs b/src/librustc_mir/borrow_check/diagnostics/var_name.rs
index 9e3d2a7..5f3585c 100644
--- a/src/librustc_mir/borrow_check/diagnostics/var_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/var_name.rs
@@ -16,7 +16,7 @@
         fr: RegionVid,
     ) -> Option<(Option<Symbol>, Span)> {
         debug!("get_var_name_and_span_for_region(fr={:?})", fr);
-        assert!(self.universal_regions.is_universal_region(fr));
+        assert!(self.universal_regions().is_universal_region(fr));
 
         debug!("get_var_name_and_span_for_region: attempting upvar");
         self.get_upvar_index_for_region(tcx, fr)
@@ -35,7 +35,7 @@
     /// Search the upvars (if any) to find one that references fr. Return its index.
     crate fn get_upvar_index_for_region(&self, tcx: TyCtxt<'tcx>, fr: RegionVid) -> Option<usize> {
         let upvar_index =
-            self.universal_regions.defining_ty.upvar_tys(tcx).position(|upvar_ty| {
+            self.universal_regions().defining_ty.upvar_tys(tcx).position(|upvar_ty| {
                 debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty);
                 tcx.any_free_region_meets(&upvar_ty, |r| {
                     let r = r.to_region_vid();
@@ -44,7 +44,7 @@
                 })
             })?;
 
-        let upvar_ty = self.universal_regions.defining_ty.upvar_tys(tcx).nth(upvar_index);
+        let upvar_ty = self.universal_regions().defining_ty.upvar_tys(tcx).nth(upvar_index);
 
         debug!(
             "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}",
@@ -85,9 +85,9 @@
         tcx: TyCtxt<'tcx>,
         fr: RegionVid,
     ) -> Option<usize> {
-        let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
+        let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
         let argument_index =
-            self.universal_regions.unnormalized_input_tys.iter().skip(implicit_inputs).position(
+            self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
                 |arg_ty| {
                     debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty);
                     tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
@@ -96,7 +96,9 @@
 
         debug!(
             "get_argument_index_for_region: found {:?} in argument {} which has type {:?}",
-            fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index],
+            fr,
+            argument_index,
+            self.universal_regions().unnormalized_input_tys[argument_index],
         );
 
         Some(argument_index)
@@ -110,7 +112,7 @@
         local_names: &IndexVec<Local, Option<Symbol>>,
         argument_index: usize,
     ) -> (Option<Symbol>, Span) {
-        let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
+        let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
         let argument_local = Local::new(implicit_inputs + argument_index + 1);
         debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local);
 
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index f9ffa21..bb56c11 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -3,7 +3,7 @@
 use rustc::mir::{BasicBlock, Body, Location, Place, ReadOnlyBodyAndCache, Rvalue};
 use rustc::mir::{BorrowKind, Mutability, Operand};
 use rustc::mir::{Statement, StatementKind};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
 
 use crate::dataflow::indexes::BorrowIndex;
@@ -16,7 +16,6 @@
 
 pub(super) fn generate_invalidates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
     body: ReadOnlyBodyAndCache<'_, 'tcx>,
@@ -33,7 +32,6 @@
         let mut ig = InvalidationGenerator {
             all_facts,
             borrow_set,
-            param_env,
             tcx,
             location_table,
             body: &body,
@@ -45,7 +43,6 @@
 
 struct InvalidationGenerator<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     all_facts: &'cx mut AllFacts,
     location_table: &'cx LocationTable,
     body: &'cx Body<'tcx>,
@@ -337,13 +334,11 @@
         );
         let tcx = self.tcx;
         let body = self.body;
-        let param_env = self.param_env;
         let borrow_set = self.borrow_set.clone();
         let indices = self.borrow_set.borrows.indices();
         each_borrow_involving_path(
             self,
             tcx,
-            param_env,
             body,
             location,
             (sd, place),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index fff6f03..9092706 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1,17 +1,18 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
-use rustc::infer::{opaque_types, InferCtxt};
+use rustc::infer::InferCtxt;
 use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::mir::{
     read_only, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability, Operand, Place,
-    PlaceBase, PlaceElem, PlaceRef, ReadOnlyBodyAndCache, Static, StaticKind,
+    PlaceElem, PlaceRef, ReadOnlyBodyAndCache,
 };
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, RegionVid, TyCtxt};
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
@@ -21,6 +22,7 @@
 use rustc_index::vec::IndexVec;
 
 use smallvec::SmallVec;
+use std::cell::RefCell;
 use std::collections::BTreeMap;
 use std::mem;
 use std::rc::Rc;
@@ -39,9 +41,7 @@
 use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use crate::transform::MirSource;
 
-use self::diagnostics::{
-    AccessKind, OutlivesSuggestionBuilder, RegionErrorKind, RegionErrorNamingCtx, RegionErrors,
-};
+use self::diagnostics::{AccessKind, RegionName};
 use self::flows::Flows;
 use self::location::LocationTable;
 use self::prefixes::PrefixSet;
@@ -239,7 +239,7 @@
         def_id,
         &attributes,
         &dead_unwinds,
-        Borrows::new(tcx, &body, param_env, regioncx.clone(), &borrow_set),
+        Borrows::new(tcx, &body, regioncx.clone(), &borrow_set),
         |rs, i| DebugFormatted::new(&rs.location(i)),
     ));
     let flow_uninits = FlowAtLocation::new(do_dataflow(
@@ -275,7 +275,6 @@
         infcx,
         body,
         mir_def_id: def_id,
-        param_env,
         move_data: &mdpe.move_data,
         location_table,
         movable_generator,
@@ -286,13 +285,15 @@
         move_error_reported: BTreeMap::new(),
         uninitialized_error_reported: Default::default(),
         errors_buffer,
-        nonlexical_regioncx: regioncx,
+        regioncx,
         used_mut: Default::default(),
         used_mut_upvars: SmallVec::new(),
         borrow_set,
         dominators,
         upvars,
         local_names,
+        region_names: RefCell::default(),
+        next_region_name: RefCell::new(1),
     };
 
     // Compute and report region errors, if any.
@@ -418,7 +419,6 @@
     crate infcx: &'cx InferCtxt<'cx, 'tcx>,
     body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     mir_def_id: DefId,
-    param_env: ty::ParamEnv<'tcx>,
     move_data: &'cx MoveData<'tcx>,
 
     /// Map from MIR `Location` to `LocationIndex`; created
@@ -478,10 +478,9 @@
     /// If the function we're checking is a closure, then we'll need to report back the list of
     /// mutable upvars that have been used. This field keeps track of them.
     used_mut_upvars: SmallVec<[Field; 8]>,
-    /// Non-lexical region inference context, if NLL is enabled. This
-    /// contains the results from region inference and lets us e.g.
+    /// Region inference context. This contains the results from region inference and lets us e.g.
     /// find out which CFG points are contained in each borrow region.
-    nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
+    regioncx: Rc<RegionInferenceContext<'tcx>>,
 
     /// The set of borrows extracted from the MIR
     borrow_set: Rc<BorrowSet<'tcx>>,
@@ -494,6 +493,13 @@
 
     /// Names of local (user) variables (extracted from `var_debug_info`).
     local_names: IndexVec<Local, Option<Name>>,
+
+    /// Record the region names generated for each region in the given
+    /// MIR def so that we can reuse them later in help/error messages.
+    region_names: RefCell<FxHashMap<RegionVid, RegionName>>,
+
+    /// The counter for generating new region names.
+    next_region_name: RefCell<usize>,
 }
 
 // Check that:
@@ -633,7 +639,7 @@
 
                 debug!(
                     "visit_terminator_drop \
-                        loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
+                     loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
                     loc, term, drop_place, drop_place_ty, span
                 );
 
@@ -817,7 +823,7 @@
 }
 
 struct RootPlace<'d, 'tcx> {
-    place_base: &'d PlaceBase<'tcx>,
+    place_local: &'d Local,
     place_projection: &'d [PlaceElem<'tcx>],
     is_local_mutation_allowed: LocalMutationIsAllowed,
 }
@@ -926,13 +932,11 @@
         let tcx = self.infcx.tcx;
         let body = self.body;
         let body: &Body<'_> = &body;
-        let param_env = self.param_env;
         let location_table = self.location_table.start_index(location);
         let borrow_set = self.borrow_set.clone();
         each_borrow_involving_path(
             self,
             tcx,
-            param_env,
             body,
             location,
             (sd, place_span.0),
@@ -1255,8 +1259,8 @@
                 if let Some(field) = this.is_upvar_field_projection(place.as_ref()) {
                     this.used_mut_upvars.push(field);
                 }
-            } else if let PlaceBase::Local(local) = place.base {
-                this.used_mut.insert(local);
+            } else {
+                this.used_mut.insert(place.local);
             }
         };
 
@@ -1380,7 +1384,7 @@
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
         let deref = [ProjectionElem::Deref];
-        let mut root_place = PlaceRef { base: &place.base, projection: &[] };
+        let mut root_place = PlaceRef { local: &place.local, projection: &[] };
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
         // we just know that all locals are dropped at function exit (otherwise
@@ -1388,20 +1392,16 @@
         //
         // FIXME: allow thread-locals to borrow other thread locals?
 
-        let (might_be_alive, will_be_dropped) = match root_place.base {
-            PlaceBase::Static(_) => (true, false),
-            PlaceBase::Local(local) => {
-                if self.body.local_decls[*local].is_ref_to_thread_local() {
-                    // Thread-locals might be dropped after the function exits
-                    // We have to dereference the outer reference because
-                    // borrows don't conflict behind shared references.
-                    root_place.projection = &deref;
-                    (true, true)
-                } else {
-                    (false, self.locals_are_invalidated_at_exit)
-                }
-            }
-        };
+        let (might_be_alive, will_be_dropped) =
+            if self.body.local_decls[*root_place.local].is_ref_to_thread_local() {
+                // Thread-locals might be dropped after the function exits
+                // We have to dereference the outer reference because
+                // borrows don't conflict behind shared references.
+                root_place.projection = &deref;
+                (true, true)
+            } else {
+                (false, self.locals_are_invalidated_at_exit)
+            };
 
         if !will_be_dropped {
             debug!("place_is_invalidated_at_exit({:?}) - won't be dropped", place);
@@ -1412,7 +1412,6 @@
 
         if places_conflict::borrow_conflicts_with_place(
             self.infcx.tcx,
-            self.param_env,
             &self.body,
             place,
             borrow.kind,
@@ -1474,120 +1473,6 @@
             // initial reservation.
         }
     }
-
-    /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
-    fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
-        // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
-        // buffered in the `MirBorrowckCtxt`.
-
-        // FIXME(mark-i-m): Would be great to get rid of the naming context.
-        let mut region_naming = RegionErrorNamingCtx::new();
-        let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
-
-        for nll_error in nll_errors.into_iter() {
-            match nll_error {
-                RegionErrorKind::TypeTestDoesNotLiveLongEnough { span, generic } => {
-                    // FIXME. We should handle this case better. It
-                    // indicates that we have e.g., some region variable
-                    // whose value is like `'a+'b` where `'a` and `'b` are
-                    // distinct unrelated univesal regions that are not
-                    // known to outlive one another. It'd be nice to have
-                    // some examples where this arises to decide how best
-                    // to report it; we could probably handle it by
-                    // iterating over the universal regions and reporting
-                    // an error that multiple bounds are required.
-                    self.infcx
-                        .tcx
-                        .sess
-                        .struct_span_err(span, &format!("`{}` does not live long enough", generic))
-                        .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::TypeTestGenericBoundError {
-                    span,
-                    generic,
-                    lower_bound_region,
-                } => {
-                    let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
-                    self.infcx
-                        .construct_generic_bound_failure(
-                            region_scope_tree,
-                            span,
-                            None,
-                            generic,
-                            lower_bound_region,
-                        )
-                        .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::UnexpectedHiddenRegion {
-                    opaque_type_def_id,
-                    hidden_ty,
-                    member_region,
-                } => {
-                    let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
-                    opaque_types::unexpected_hidden_region_diagnostic(
-                        self.infcx.tcx,
-                        Some(region_scope_tree),
-                        opaque_type_def_id,
-                        hidden_ty,
-                        member_region,
-                    )
-                    .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::BoundUniversalRegionError {
-                    longer_fr,
-                    fr_origin,
-                    error_region,
-                } => {
-                    // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
-                    let (_, span) = self.nonlexical_regioncx.find_outlives_blame_span(
-                        &self.body,
-                        longer_fr,
-                        fr_origin,
-                        error_region,
-                    );
-
-                    // FIXME: improve this error message
-                    self.infcx
-                        .tcx
-                        .sess
-                        .struct_span_err(span, "higher-ranked subtype error")
-                        .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
-                    if is_reported {
-                        let db = self.nonlexical_regioncx.report_error(
-                            self,
-                            longer_fr,
-                            fr_origin,
-                            shorter_fr,
-                            &mut outlives_suggestion,
-                            &mut region_naming,
-                        );
-
-                        db.buffer(&mut self.errors_buffer);
-                    } else {
-                        // We only report the first error, so as not to overwhelm the user. See
-                        // `RegRegionErrorKind` docs.
-                        //
-                        // FIXME: currently we do nothing with these, but perhaps we can do better?
-                        // FIXME: try collecting these constraints on the outlives suggestion
-                        // builder. Does it make the suggestions any better?
-                        debug!(
-                            "Unreported region error: can't prove that {:?}: {:?}",
-                            longer_fr, shorter_fr
-                        );
-                    }
-                }
-            }
-        }
-
-        // Emit one outlives suggestions for each MIR def we borrowck
-        outlives_suggestion.add_suggestion(self, &mut region_naming);
-    }
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
@@ -1654,26 +1539,20 @@
         // This code covers scenarios 1, 2, and 3.
 
         debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
-        match self.move_path_closest_to(place_span.0) {
-            Ok((prefix, mpi)) => {
-                if maybe_uninits.contains(mpi) {
-                    self.report_use_of_moved_or_uninitialized(
-                        location,
-                        desired_action,
-                        (prefix, place_span.0, place_span.1),
-                        mpi,
-                    );
-                }
-            }
-            Err(NoMovePathFound::ReachedStatic) => {
-                // Okay: we do not build MoveData for static variables
-            } // Only query longest prefix with a MovePath, not further
-              // ancestors; dataflow recurs on children when parents
-              // move (to support partial (re)inits).
-              //
-              // (I.e., querying parents breaks scenario 7; but may want
-              // to do such a query based on partial-init feature-gate.)
-        }
+        let (prefix, mpi) = self.move_path_closest_to(place_span.0);
+        if maybe_uninits.contains(mpi) {
+            self.report_use_of_moved_or_uninitialized(
+                location,
+                desired_action,
+                (prefix, place_span.0, place_span.1),
+                mpi,
+            );
+        } // Only query longest prefix with a MovePath, not further
+        // ancestors; dataflow recurs on children when parents
+        // move (to support partial (re)inits).
+        //
+        // (I.e., querying parents breaks scenario 7; but may want
+        // to do such a query based on partial-init feature-gate.)
     }
 
     /// Subslices correspond to multiple move paths, so we iterate through the
@@ -1746,9 +1625,9 @@
             place_span.0.projection
         {
             let place_ty =
-                Place::ty_from(place_span.0.base, base_proj, self.body(), self.infcx.tcx);
+                Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx);
             if let ty::Array(..) = place_ty.ty.kind {
-                let array_place = PlaceRef { base: place_span.0.base, projection: base_proj };
+                let array_place = PlaceRef { local: place_span.0.local, projection: base_proj };
                 self.check_if_subslice_element_is_moved(
                     location,
                     desired_action,
@@ -1797,12 +1676,12 @@
     fn move_path_closest_to(
         &mut self,
         place: PlaceRef<'_, 'tcx>,
-    ) -> Result<(PlaceRef<'cx, 'tcx>, MovePathIndex), NoMovePathFound> {
+    ) -> (PlaceRef<'cx, 'tcx>, MovePathIndex) {
         match self.move_data.rev_lookup.find(place) {
             LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
-                Ok((self.move_data.move_paths[mpi].place.as_ref(), mpi))
+                (self.move_data.move_paths[mpi].place.as_ref(), mpi)
             }
-            LookupResult::Parent(None) => Err(NoMovePathFound::ReachedStatic),
+            LookupResult::Parent(None) => panic!("should have move path for every Local"),
         }
     }
 
@@ -1845,7 +1724,7 @@
                     self.check_if_full_path_is_moved(
                         location, InitializationRequiringAction::Use,
                         (PlaceRef {
-                            base: &place.base,
+                            local: &place.local,
                             projection: proj_base,
                         }, span), flow_state);
                     // (base initialized; no need to
@@ -1863,13 +1742,13 @@
                     // assigning to `P.f` requires `P` itself
                     // be already initialized
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(&place.base, proj_base, self.body(), tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, self.body(), tcx).ty;
                     match base_ty.kind {
                         ty::Adt(def, _) if def.has_dtor(tcx) => {
                             self.check_if_path_or_subpath_is_moved(
                                 location, InitializationRequiringAction::Assignment,
                                 (PlaceRef {
-                                    base: &place.base,
+                                    local: &place.local,
                                     projection: proj_base,
                                 }, span), flow_state);
 
@@ -1882,21 +1761,14 @@
                         // is allowed, remove this match arm.
                         ty::Adt(..) | ty::Tuple(..) => {
                             check_parent_of_field(self, location, PlaceRef {
-                                base: &place.base,
+                                local: &place.local,
                                 projection: proj_base,
                             }, span, flow_state);
 
-                            if let PlaceBase::Local(local) = place.base {
-                                // rust-lang/rust#21232,
-                                // #54499, #54986: during
-                                // period where we reject
-                                // partial initialization, do
-                                // not complain about
-                                // unnecessary `mut` on an
-                                // attempt to do a partial
-                                // initialization.
-                                self.used_mut.insert(local);
-                            }
+                            // rust-lang/rust#21232, #54499, #54986: during period where we reject
+                            // partial initialization, do not complain about unnecessary `mut` on
+                            // an attempt to do a partial initialization.
+                            self.used_mut.insert(place.local);
                         }
 
                         _ => {}
@@ -1974,7 +1846,7 @@
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
                 if let ty::Adt(def, _) =
-                    Place::ty_from(base.base, base.projection, this.body(), tcx).ty.kind
+                    Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind
                 {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
@@ -2093,11 +1965,8 @@
         // partial initialization, do not complain about mutability
         // errors except for actual mutation (as opposed to an attempt
         // to do a partial initialization).
-        let previously_initialized = if let PlaceBase::Local(local) = place.base {
-            self.is_local_ever_initialized(local, flow_state).is_some()
-        } else {
-            true
-        };
+        let previously_initialized =
+            self.is_local_ever_initialized(place.local, flow_state).is_some();
 
         // at this point, we have set up the error reporting state.
         if previously_initialized {
@@ -2126,11 +1995,7 @@
     /// Adds the place into the used mutable variables set
     fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) {
         match root_place {
-            RootPlace {
-                place_base: PlaceBase::Local(local),
-                place_projection: [],
-                is_local_mutation_allowed,
-            } => {
+            RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
                 // mutated, then it is justified to be annotated with the `mut`
                 // keyword, since the mutation may be a possible reassignment.
@@ -2141,27 +2006,22 @@
                 }
             }
             RootPlace {
-                place_base: _,
+                place_local: _,
                 place_projection: _,
                 is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
             } => {}
             RootPlace {
-                place_base,
+                place_local,
                 place_projection: place_projection @ [.., _],
                 is_local_mutation_allowed: _,
             } => {
                 if let Some(field) = self.is_upvar_field_projection(PlaceRef {
-                    base: &place_base,
-                    projection: &place_projection,
+                    local: place_local,
+                    projection: place_projection,
                 }) {
                     self.used_mut_upvars.push(field);
                 }
             }
-            RootPlace {
-                place_base: PlaceBase::Static(..),
-                place_projection: [],
-                is_local_mutation_allowed: _,
-            } => {}
         }
     }
 
@@ -2173,58 +2033,34 @@
         is_local_mutation_allowed: LocalMutationIsAllowed,
     ) -> Result<RootPlace<'d, 'tcx>, PlaceRef<'d, 'tcx>> {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
+            PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[*local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
                         LocalMutationIsAllowed::Yes => Ok(RootPlace {
-                            place_base: place.base,
+                            place_local: place.local,
                             place_projection: place.projection,
                             is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
                         }),
                         LocalMutationIsAllowed::ExceptUpvars => Ok(RootPlace {
-                            place_base: place.base,
+                            place_local: place.local,
                             place_projection: place.projection,
                             is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars,
                         }),
                         LocalMutationIsAllowed::No => Err(place),
                     },
                     Mutability::Mut => Ok(RootPlace {
-                        place_base: place.base,
+                        place_local: place.local,
                         place_projection: place.projection,
                         is_local_mutation_allowed,
                     }),
                 }
             }
-            // The rules for promotion are made by `qualify_consts`, there wouldn't even be a
-            // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }),
-                projection: [],
-            } => Ok(RootPlace {
-                place_base: place.base,
-                place_projection: place.projection,
-                is_local_mutation_allowed,
-            }),
-            PlaceRef {
-                base: PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }),
-                projection: [],
-            } => {
-                if !self.infcx.tcx.is_mutable_static(*def_id) {
-                    Err(place)
-                } else {
-                    Ok(RootPlace {
-                        place_base: place.base,
-                        place_projection: place.projection,
-                        is_local_mutation_allowed,
-                    })
-                }
-            }
-            PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local: _, projection: [proj_base @ .., 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.local, proj_base, self.body(), self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.kind {
@@ -2243,7 +2079,7 @@
                                         };
 
                                         self.is_mutable(
-                                            PlaceRef { base: place.base, projection: proj_base },
+                                            PlaceRef { local: place.local, projection: proj_base },
                                             mode,
                                         )
                                     }
@@ -2256,7 +2092,7 @@
                                     // `*mut` raw pointers are always mutable, regardless of
                                     // context. The users have to check by themselves.
                                     hir::Mutability::Mut => Ok(RootPlace {
-                                        place_base: place.base,
+                                        place_local: place.local,
                                         place_projection: place.projection,
                                         is_local_mutation_allowed,
                                     }),
@@ -2264,7 +2100,7 @@
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable
                             _ if base_ty.is_box() => self.is_mutable(
-                                PlaceRef { base: place.base, projection: proj_base },
+                                PlaceRef { local: place.local, projection: proj_base },
                                 is_local_mutation_allowed,
                             ),
                             // Deref should only be for reference, pointers or boxes
@@ -2283,7 +2119,7 @@
                             let upvar = &self.upvars[field.index()];
                             debug!(
                                 "upvar.mutability={:?} local_mutation_is_allowed={:?} \
-                                place={:?}",
+                                 place={:?}",
                                 upvar, is_local_mutation_allowed, place
                             );
                             match (upvar.mutability, is_local_mutation_allowed) {
@@ -2320,11 +2156,11 @@
                                     // }
                                     // ```
                                     let _ = self.is_mutable(
-                                        PlaceRef { base: place.base, projection: proj_base },
+                                        PlaceRef { local: place.local, projection: proj_base },
                                         is_local_mutation_allowed,
                                     )?;
                                     Ok(RootPlace {
-                                        place_base: place.base,
+                                        place_local: place.local,
                                         place_projection: place.projection,
                                         is_local_mutation_allowed,
                                     })
@@ -2332,7 +2168,7 @@
                             }
                         } else {
                             self.is_mutable(
-                                PlaceRef { base: place.base, projection: proj_base },
+                                PlaceRef { local: place.local, projection: proj_base },
                                 is_local_mutation_allowed,
                             )
                         }
@@ -2358,7 +2194,7 @@
         match place_projection {
             [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.local, base, self.body(), tcx).ty;
 
                 if (base_ty.is_closure() || base_ty.is_generator())
                     && (!by_ref || self.upvars[field.index()].by_ref)
@@ -2374,11 +2210,6 @@
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum NoMovePathFound {
-    ReachedStatic,
-}
-
 /// The degree of overlap between 2 places for borrow-checking.
 enum Overlap {
     /// The places might partially overlap - in this case, we give
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index a4c2299..73718d5 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -231,7 +231,6 @@
 
     constraint_generation::generate_constraints(
         infcx,
-        param_env,
         &mut liveness_constraints,
         &mut all_facts,
         location_table,
@@ -253,14 +252,7 @@
     );
 
     // Generate various additional constraints.
-    invalidation::generate_invalidates(
-        infcx.tcx,
-        param_env,
-        &mut all_facts,
-        location_table,
-        body,
-        borrow_set,
-    );
+    invalidation::generate_invalidates(infcx.tcx, &mut all_facts, location_table, body, borrow_set);
 
     // Dump facts if requested.
     let polonius_output = all_facts.and_then(|all_facts| {
@@ -368,7 +360,7 @@
     // better.
 
     if let Some(closure_region_requirements) = closure_region_requirements {
-        let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "External requirements");
+        let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements");
 
         regioncx.annotate(tcx, &mut err);
 
@@ -387,7 +379,7 @@
 
         err.buffer(errors_buffer);
     } else {
-        let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "No external requirements");
+        let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements");
         regioncx.annotate(tcx, &mut err);
 
         err.buffer(errors_buffer);
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 23b4799..deec6f3 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -3,8 +3,8 @@
 use crate::borrow_check::AccessDepth;
 use crate::dataflow::indexes::BorrowIndex;
 use rustc::mir::BorrowKind;
-use rustc::mir::{BasicBlock, Body, Location, Place, PlaceBase};
-use rustc::ty::{self, TyCtxt};
+use rustc::mir::{BasicBlock, Body, Location, Place};
+use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
 
 /// Returns `true` if the borrow represented by `kind` is
@@ -25,7 +25,6 @@
 pub(super) fn each_borrow_involving_path<'tcx, F, I, S>(
     s: &mut S,
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     _location: Location,
     access_place: (AccessDepth, &Place<'tcx>),
@@ -48,7 +47,6 @@
 
         if places_conflict::borrow_conflicts_with_place(
             tcx,
-            param_env,
             body,
             &borrowed.borrowed_place,
             borrowed.kind,
@@ -133,11 +131,7 @@
 /// Determines if a given borrow is borrowing local data
 /// This is called for all Yield expressions on movable generators
 pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
-    match place.base {
-        PlaceBase::Static(_) => false,
-
-        // Reborrow of already borrowed data is ignored
-        // Any errors will be caught on the initial borrow
-        PlaceBase::Local(_) => !place.is_indirect(),
-    }
+    // Reborrow of already borrowed data is ignored
+    // Any errors will be caught on the initial borrow
+    !place.is_indirect()
 }
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index 91ab314..ac02da2 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -1,6 +1,6 @@
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
 use rustc::mir::ProjectionElem;
-use rustc::mir::{Body, Mutability, Place, PlaceBase};
+use rustc::mir::{Body, Mutability, Place};
 use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
 
@@ -25,41 +25,35 @@
         body: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
-        let local = 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(local) => match locals_state_at_exit {
-                LocalsStateAtExit::AllAreInvalidated => local,
-                LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
-                    let ignore = !has_storage_dead_or_moved.contains(local)
-                        && body.local_decls[local].mutability == Mutability::Not;
-                    debug!("ignore_borrow: local {:?} => {:?}", local, ignore);
-                    if ignore {
-                        return true;
-                    } else {
-                        local
-                    }
-                }
-            },
-            PlaceBase::Static(_) => return true,
-        };
+        // 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.
+        if let LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } =
+            locals_state_at_exit
+        {
+            let ignore = !has_storage_dead_or_moved.contains(self.local)
+                && body.local_decls[self.local].mutability == Mutability::Not;
+            debug!("ignore_borrow: local {:?} => {:?}", self.local, ignore);
+            if ignore {
+                return true;
+            }
+        }
 
         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;
+                let ty = Place::ty_from(&self.local, proj_base, body, tcx).ty;
                 match ty.kind {
                     ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
                         // For references to thread-local statics, we do need
                         // to track the borrow.
-                        if body.local_decls[local].is_ref_to_thread_local() {
+                        if body.local_decls[self.local].is_ref_to_thread_local() {
                             continue;
                         }
                         return true;
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 6410371..b95d1af 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -1,9 +1,7 @@
 use crate::borrow_check::ArtificialField;
 use crate::borrow_check::Overlap;
 use crate::borrow_check::{AccessDepth, Deep, Shallow};
-use rustc::mir::{
-    Body, BorrowKind, Place, PlaceBase, PlaceElem, PlaceRef, ProjectionElem, StaticKind,
-};
+use rustc::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
 use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
 use std::cmp::max;
@@ -25,7 +23,6 @@
 /// dataflow).
 crate fn places_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     access_place: &Place<'tcx>,
@@ -33,7 +30,6 @@
 ) -> bool {
     borrow_conflicts_with_place(
         tcx,
-        param_env,
         body,
         borrow_place,
         BorrowKind::Mut { allow_two_phase_borrow: true },
@@ -49,7 +45,6 @@
 /// order to make the conservative choice and preserve soundness.
 pub(super) fn borrow_conflicts_with_place<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
@@ -70,21 +65,11 @@
         }
     }
 
-    place_components_conflict(
-        tcx,
-        param_env,
-        body,
-        borrow_place,
-        borrow_kind,
-        access_place,
-        access,
-        bias,
-    )
+    place_components_conflict(tcx, 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_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
@@ -134,10 +119,10 @@
     //    and either equal or disjoint.
     //  - If we did run out of access, the borrow can access a part of it.
 
-    let borrow_base = &borrow_place.base;
-    let access_base = access_place.base;
+    let borrow_local = &borrow_place.local;
+    let access_local = access_place.local;
 
-    match place_base_conflict(tcx, param_env, borrow_base, access_base) {
+    match place_base_conflict(borrow_local, access_local) {
         Overlap::Arbitrary => {
             bug!("Two base can't return Arbitrary");
         }
@@ -176,7 +161,7 @@
         match place_projection_conflict(
             tcx,
             body,
-            borrow_base,
+            borrow_local,
             borrow_proj_base,
             borrow_c,
             access_c,
@@ -223,7 +208,7 @@
             // 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;
+            let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
 
             match (elem, &base_ty.kind, access) {
                 (_, _, Shallow(Some(ArtificialField::ArrayLength)))
@@ -308,68 +293,15 @@
 // Given that the bases of `elem1` and `elem2` are always either equal
 // or disjoint (and have the same type!), return the overlap situation
 // between `elem1` and `elem2`.
-fn place_base_conflict<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    elem1: &PlaceBase<'tcx>,
-    elem2: &PlaceBase<'tcx>,
-) -> Overlap {
-    match (elem1, elem2) {
-        (PlaceBase::Local(l1), PlaceBase::Local(l2)) => {
-            if l1 == l2 {
-                // the same local - base case, equal
-                debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
-                Overlap::EqualOrDisjoint
-            } else {
-                // different locals - base case, disjoint
-                debug!("place_element_conflict: DISJOINT-LOCAL");
-                Overlap::Disjoint
-            }
-        }
-        (PlaceBase::Static(s1), PlaceBase::Static(s2)) => {
-            match (&s1.kind, &s2.kind) {
-                (StaticKind::Static, StaticKind::Static) => {
-                    if s1.def_id != s2.def_id {
-                        debug!("place_element_conflict: DISJOINT-STATIC");
-                        Overlap::Disjoint
-                    } else if tcx.is_mutable_static(s1.def_id) {
-                        // We ignore mutable statics - they can only be unsafe code.
-                        debug!("place_element_conflict: IGNORE-STATIC-MUT");
-                        Overlap::Disjoint
-                    } else {
-                        debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
-                        Overlap::EqualOrDisjoint
-                    }
-                }
-                (StaticKind::Promoted(promoted_1, _), StaticKind::Promoted(promoted_2, _)) => {
-                    if promoted_1 == promoted_2 {
-                        if let ty::Array(_, len) = s1.ty.kind {
-                            if let Some(0) = len.try_eval_usize(tcx, param_env) {
-                                // Ignore conflicts with promoted [T; 0].
-                                debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
-                                return Overlap::Disjoint;
-                            }
-                        }
-                        // the same promoted - base case, equal
-                        debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
-                        Overlap::EqualOrDisjoint
-                    } else {
-                        // different promoteds - base case, disjoint
-                        debug!("place_element_conflict: DISJOINT-PROMOTED");
-                        Overlap::Disjoint
-                    }
-                }
-                (_, _) => {
-                    debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
-                    Overlap::Disjoint
-                }
-            }
-        }
-        (PlaceBase::Local(_), PlaceBase::Static(_))
-        | (PlaceBase::Static(_), PlaceBase::Local(_)) => {
-            debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
-            Overlap::Disjoint
-        }
+fn place_base_conflict(l1: &Local, l2: &Local) -> Overlap {
+    if l1 == l2 {
+        // the same local - base case, equal
+        debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
+        Overlap::EqualOrDisjoint
+    } else {
+        // different locals - base case, disjoint
+        debug!("place_element_conflict: DISJOINT-LOCAL");
+        Overlap::Disjoint
     }
 }
 
@@ -379,7 +311,7 @@
 fn place_projection_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
-    pi1_base: &PlaceBase<'tcx>,
+    pi1_local: &Local,
     pi1_proj_base: &[PlaceElem<'tcx>],
     pi1_elem: &PlaceElem<'tcx>,
     pi2_elem: &PlaceElem<'tcx>,
@@ -397,7 +329,7 @@
                 debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
                 Overlap::EqualOrDisjoint
             } else {
-                let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty;
+                let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
                 match ty.kind {
                     ty::Adt(def, _) if def.is_union() => {
                         // Different fields of a union, we are basically stuck.
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 1e88f69..31bee46 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -9,7 +9,7 @@
 
 use super::MirBorrowckCtxt;
 
-use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
+use rustc::mir::{Place, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
 use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
 
@@ -19,7 +19,7 @@
 
 impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
     fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
-        self.base == other.base
+        self.local == other.local
             && self.projection.len() <= other.projection.len()
             && self.projection == &other.projection[..self.projection.len()]
     }
@@ -69,39 +69,23 @@
 
         'cursor: loop {
             match &cursor {
-                PlaceRef {
-                    base: PlaceBase::Local(_),
-                    projection: [],
-                }
-                | // search yielded this leaf
-                PlaceRef {
-                    base: PlaceBase::Static(_),
-                    projection: [],
-                } => {
+                PlaceRef { local: _, projection: [] } => {
                     self.next = None;
                     return Some(cursor);
                 }
-                PlaceRef {
-                    base: _,
-                    projection: [proj_base @ .., elem],
-                } => {
+                PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
                     match elem {
                         ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
                             // FIXME: add union handling
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
-                        ProjectionElem::Downcast(..) |
-                        ProjectionElem::Subslice { .. } |
-                        ProjectionElem::ConstantIndex { .. } |
-                        ProjectionElem::Index(_) => {
-                            cursor = PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            };
+                        ProjectionElem::Downcast(..)
+                        | ProjectionElem::Subslice { .. }
+                        | ProjectionElem::ConstantIndex { .. }
+                        | ProjectionElem::Index(_) => {
+                            cursor = PlaceRef { local: cursor.local, projection: proj_base };
                             continue 'cursor;
                         }
                         ProjectionElem::Deref => {
@@ -122,10 +106,8 @@
                         PrefixSet::All => {
                             // All prefixes: just blindly enqueue the base
                             // of the projection.
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
                         PrefixSet::Supporting => {
@@ -138,37 +120,24 @@
                     // 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;
+                    let ty = Place::ty_from(cursor.local, proj_base, *self.body, self.tcx).ty;
                     match ty.kind {
-                        ty::RawPtr(_) |
-                        ty::Ref(
-                            _, /*rgn*/
-                            _, /*ty*/
-                            hir::Mutability::Not
-                            ) => {
+                        ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
                             // don't continue traversing over derefs of raw pointers or shared
                             // borrows.
                             self.next = None;
                             return Some(cursor);
                         }
 
-                        ty::Ref(
-                            _, /*rgn*/
-                            _, /*ty*/
-                            hir::Mutability::Mut,
-                            ) => {
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                        ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => {
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
 
                         ty::Adt(..) if ty.is_box() => {
-                            self.next = Some(PlaceRef {
-                                base: cursor.base,
-                                projection: proj_base,
-                            });
+                            self.next =
+                                Some(PlaceRef { local: cursor.local, projection: proj_base });
                             return Some(cursor);
                         }
 
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 7d2384f..26d9cf2 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -1,3 +1,4 @@
+use std::collections::VecDeque;
 use std::rc::Rc;
 
 use rustc::infer::canonical::QueryOutlivesConstraint;
@@ -43,49 +44,48 @@
     /// variables are identified by their index (`RegionVid`). The
     /// definition contains information about where the region came
     /// from as well as its final inferred value.
-    pub(in crate::borrow_check) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
+    definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
 
     /// The liveness constraints added to each region. For most
     /// regions, these start out empty and steadily grow, though for
     /// each universally quantified region R they start out containing
     /// the entire CFG and `end(R)`.
-    pub(in crate::borrow_check) liveness_constraints: LivenessValues<RegionVid>,
+    liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    pub(in crate::borrow_check) constraints: Rc<OutlivesConstraintSet>,
+    constraints: Rc<OutlivesConstraintSet>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
     /// the SCC (see `constraint_sccs`) and for error reporting.
-    pub(in crate::borrow_check) constraint_graph: Rc<NormalConstraintGraph>,
+    constraint_graph: Rc<NormalConstraintGraph>,
 
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
     /// compute the values of each region.
-    pub(in crate::borrow_check) constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+    constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
     /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
     /// exists if `B: A`. Computed lazilly.
-    pub(in crate::borrow_check) rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+    rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
 
     /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
-    pub(in crate::borrow_check) member_constraints:
-        Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+    member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
 
     /// Records the member constraints that we applied to each scc.
     /// This is useful for error reporting. Once constraint
     /// propagation is done, this vector is sorted according to
     /// `member_region_scc`.
-    pub(in crate::borrow_check) member_constraints_applied: Vec<AppliedMemberConstraint>,
+    member_constraints_applied: Vec<AppliedMemberConstraint>,
 
     /// Map closure bounds to a `Span` that should be used for error reporting.
-    pub(in crate::borrow_check) closure_bounds_mapping:
+    closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
     /// visible from this index.
-    pub(in crate::borrow_check) scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
+    scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
 
     /// Contains a "representative" from each SCC. This will be the
     /// minimal RegionVid belonging to that universe. It is used as a
@@ -94,23 +94,23 @@
     /// of its SCC and be sure that -- if they have the same repr --
     /// they *must* be equal (though not having the same repr does not
     /// mean they are unequal).
-    pub(in crate::borrow_check) scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
+    scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
 
     /// The final inferred values of the region variables; we compute
     /// one value per SCC. To get the value for any given *region*,
     /// you first find which scc it is a part of.
-    pub(in crate::borrow_check) scc_values: RegionValues<ConstraintSccIndex>,
+    scc_values: RegionValues<ConstraintSccIndex>,
 
     /// Type constraints that we check after solving.
-    pub(in crate::borrow_check) type_tests: Vec<TypeTest<'tcx>>,
+    type_tests: Vec<TypeTest<'tcx>>,
 
     /// Information about the universally quantified regions in scope
     /// on this function.
-    pub(in crate::borrow_check) universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: Rc<UniversalRegions<'tcx>>,
 
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
-    pub(in crate::borrow_check) universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
 }
 
 /// Each time that `apply_member_constraint` is successful, it appends
@@ -225,6 +225,13 @@
     Error,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum Trace {
+    StartRegion,
+    FromOutlivesConstraint(OutlivesConstraint),
+    NotVisited,
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Creates a new region inference context with a total of
     /// `num_region_variables` valid inference variables; the first N
@@ -838,39 +845,22 @@
             }
 
             // Type-test failed. Report the error.
-
-            // Try to convert the lower-bound region into something named we can print for the user.
-            let lower_bound_region = self.to_error_region(type_test.lower_bound);
+            let erased_generic_kind = infcx.tcx.erase_regions(&type_test.generic_kind);
 
             // Skip duplicate-ish errors.
-            let type_test_span = type_test.locations.span(body);
-            let erased_generic_kind = tcx.erase_regions(&type_test.generic_kind);
-            if !deduplicate_errors.insert((
+            if deduplicate_errors.insert((
                 erased_generic_kind,
-                lower_bound_region,
+                type_test.lower_bound,
                 type_test.locations,
             )) {
-                continue;
-            } else {
                 debug!(
                     "check_type_test: reporting error for erased_generic_kind={:?}, \
                      lower_bound_region={:?}, \
                      type_test.locations={:?}",
-                    erased_generic_kind, lower_bound_region, type_test.locations,
+                    erased_generic_kind, type_test.lower_bound, type_test.locations,
                 );
-            }
 
-            if let Some(lower_bound_region) = lower_bound_region {
-                errors_buffer.push(RegionErrorKind::TypeTestGenericBoundError {
-                    span: type_test_span,
-                    generic: type_test.generic_kind,
-                    lower_bound_region,
-                });
-            } else {
-                errors_buffer.push(RegionErrorKind::TypeTestDoesNotLiveLongEnough {
-                    span: type_test_span,
-                    generic: type_test.generic_kind,
-                });
+                errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
             }
         }
     }
@@ -1355,7 +1345,7 @@
         for (longer_fr, shorter_fr) in subset_errors.into_iter() {
             debug!(
                 "check_polonius_subset_errors: subset_error longer_fr={:?},\
-                shorter_fr={:?}",
+                 shorter_fr={:?}",
                 longer_fr, shorter_fr
             );
 
@@ -1572,23 +1562,9 @@
         debug!("check_bound_universal_region: error_element = {:?}", error_element);
 
         // Find the region that introduced this `error_element`.
-        let error_region = match error_element {
-            RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
-            RegionElement::RootUniversalRegion(r) => r,
-            RegionElement::PlaceholderRegion(error_placeholder) => self
-                .definitions
-                .iter_enumerated()
-                .filter_map(|(r, definition)| match definition.origin {
-                    NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
-                    _ => None,
-                })
-                .next()
-                .unwrap(),
-        };
-
         errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
             longer_fr,
-            error_region,
+            error_element,
             fr_origin: NLLRegionVariableOrigin::Placeholder(placeholder),
         });
     }
@@ -1628,6 +1604,425 @@
             });
         }
     }
+
+    /// We have a constraint `fr1: fr2` that is not satisfied, where
+    /// `fr2` represents some universal region. Here, `r` is some
+    /// region where we know that `fr1: r` and this function has the
+    /// job of determining whether `r` is "to blame" for the fact that
+    /// `fr1: fr2` is required.
+    ///
+    /// This is true under two conditions:
+    ///
+    /// - `r == fr2`
+    /// - `fr2` is `'static` and `r` is some placeholder in a universe
+    ///   that cannot be named by `fr1`; in that case, we will require
+    ///   that `fr1: 'static` because it is the only way to `fr1: r` to
+    ///   be satisfied. (See `add_incompatible_universe`.)
+    crate fn provides_universal_region(
+        &self,
+        r: RegionVid,
+        fr1: RegionVid,
+        fr2: RegionVid,
+    ) -> bool {
+        debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
+        let result = {
+            r == fr2 || {
+                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
+            }
+        };
+        debug!("provides_universal_region: result = {:?}", result);
+        result
+    }
+
+    /// If `r2` represents a placeholder region, then this returns
+    /// `true` if `r1` cannot name that placeholder in its
+    /// value; otherwise, returns `false`.
+    crate fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
+        debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2);
+
+        match self.definitions[r2].origin {
+            NLLRegionVariableOrigin::Placeholder(placeholder) => {
+                let universe1 = self.definitions[r1].universe;
+                debug!(
+                    "cannot_name_value_of: universe1={:?} placeholder={:?}",
+                    universe1, placeholder
+                );
+                universe1.cannot_name(placeholder.universe)
+            }
+
+            NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => {
+                false
+            }
+        }
+    }
+
+    crate fn retrieve_closure_constraint_info(
+        &self,
+        body: &Body<'tcx>,
+        constraint: &OutlivesConstraint,
+    ) -> (ConstraintCategory, bool, Span) {
+        let loc = match constraint.locations {
+            Locations::All(span) => return (constraint.category, false, span),
+            Locations::Single(loc) => loc,
+        };
+
+        let opt_span_category =
+            self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
+        opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or((
+            constraint.category,
+            false,
+            body.source_info(loc).span,
+        ))
+    }
+
+    /// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
+    crate fn find_outlives_blame_span(
+        &self,
+        body: &Body<'tcx>,
+        fr1: RegionVid,
+        fr1_origin: NLLRegionVariableOrigin,
+        fr2: RegionVid,
+    ) -> (ConstraintCategory, Span) {
+        let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| {
+            self.provides_universal_region(r, fr1, fr2)
+        });
+        (category, span)
+    }
+
+    /// Walks the graph of constraints (where `'a: 'b` is considered
+    /// an edge `'a -> 'b`) to find all paths from `from_region` to
+    /// `to_region`. The paths are accumulated into the vector
+    /// `results`. The paths are stored as a series of
+    /// `ConstraintIndex` values -- in other words, a list of *edges*.
+    ///
+    /// Returns: a series of constraints as well as the region `R`
+    /// that passed the target test.
+    crate fn find_constraint_paths_between_regions(
+        &self,
+        from_region: RegionVid,
+        target_test: impl Fn(RegionVid) -> bool,
+    ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
+        let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
+        context[from_region] = Trace::StartRegion;
+
+        // Use a deque so that we do a breadth-first search. We will
+        // stop at the first match, which ought to be the shortest
+        // path (fewest constraints).
+        let mut deque = VecDeque::new();
+        deque.push_back(from_region);
+
+        while let Some(r) = deque.pop_front() {
+            debug!(
+                "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
+                from_region,
+                r,
+                self.region_value_str(r),
+            );
+
+            // Check if we reached the region we were looking for. If so,
+            // we can reconstruct the path that led to it and return it.
+            if target_test(r) {
+                let mut result = vec![];
+                let mut p = r;
+                loop {
+                    match context[p] {
+                        Trace::NotVisited => {
+                            bug!("found unvisited region {:?} on path to {:?}", p, r)
+                        }
+
+                        Trace::FromOutlivesConstraint(c) => {
+                            result.push(c);
+                            p = c.sup;
+                        }
+
+                        Trace::StartRegion => {
+                            result.reverse();
+                            return Some((result, r));
+                        }
+                    }
+                }
+            }
+
+            // Otherwise, walk over the outgoing constraints and
+            // enqueue any regions we find, keeping track of how we
+            // reached them.
+
+            // A constraint like `'r: 'x` can come from our constraint
+            // graph.
+            let fr_static = self.universal_regions.fr_static;
+            let outgoing_edges_from_graph =
+                self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
+
+            // Always inline this closure because it can be hot.
+            let mut handle_constraint = #[inline(always)]
+            |constraint: OutlivesConstraint| {
+                debug_assert_eq!(constraint.sup, r);
+                let sub_region = constraint.sub;
+                if let Trace::NotVisited = context[sub_region] {
+                    context[sub_region] = Trace::FromOutlivesConstraint(constraint);
+                    deque.push_back(sub_region);
+                }
+            };
+
+            // This loop can be hot.
+            for constraint in outgoing_edges_from_graph {
+                handle_constraint(constraint);
+            }
+
+            // Member constraints can also give rise to `'r: 'x` edges that
+            // were not part of the graph initially, so watch out for those.
+            // (But they are extremely rare; this loop is very cold.)
+            for constraint in self.applied_member_constraints(r) {
+                let p_c = &self.member_constraints[constraint.member_constraint_index];
+                let constraint = OutlivesConstraint {
+                    sup: r,
+                    sub: constraint.min_choice,
+                    locations: Locations::All(p_c.definition_span),
+                    category: ConstraintCategory::OpaqueType,
+                };
+                handle_constraint(constraint);
+            }
+        }
+
+        None
+    }
+
+    /// Finds some region R such that `fr1: R` and `R` is live at `elem`.
+    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
+        debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
+        self.find_constraint_paths_between_regions(fr1, |r| {
+            // First look for some `r` such that `fr1: r` and `r` is live at `elem`
+            debug!(
+                "find_sub_region_live_at: liveness_constraints for {:?} are {:?}",
+                r,
+                self.liveness_constraints.region_value_str(r),
+            );
+            self.liveness_constraints.contains(r, elem)
+        })
+        .or_else(|| {
+            // If we fail to find that, we may find some `r` such that
+            // `fr1: r` and `r` is a placeholder from some universe
+            // `fr1` cannot name. This would force `fr1` to be
+            // `'static`.
+            self.find_constraint_paths_between_regions(fr1, |r| {
+                self.cannot_name_placeholder(fr1, r)
+            })
+        })
+        .or_else(|| {
+            // If we fail to find THAT, it may be that `fr1` is a
+            // placeholder that cannot "fit" into its SCC. In that
+            // case, there should be some `r` where `fr1: r`, both
+            // `fr1` and `r` are in the same SCC, and `fr1` is a
+            // placeholder that `r` cannot name. We can blame that
+            // edge.
+            self.find_constraint_paths_between_regions(fr1, |r| {
+                self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r)
+                    && self.cannot_name_placeholder(r, fr1)
+            })
+        })
+        .map(|(_path, r)| r)
+        .unwrap()
+    }
+
+    /// Get the region outlived by `longer_fr` and live at `element`.
+    crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid {
+        match element {
+            RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
+            RegionElement::RootUniversalRegion(r) => r,
+            RegionElement::PlaceholderRegion(error_placeholder) => self
+                .definitions
+                .iter_enumerated()
+                .filter_map(|(r, definition)| match definition.origin {
+                    NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
+                    _ => None,
+                })
+                .next()
+                .unwrap(),
+        }
+    }
+
+    /// Get the region definition of `r`.
+    crate fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> {
+        &self.definitions[r]
+    }
+
+    /// Check if the SCC of `r` contains `upper`.
+    crate fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool {
+        let r_scc = self.constraint_sccs.scc(r);
+        self.scc_values.contains(r_scc, upper)
+    }
+
+    crate fn universal_regions(&self) -> &UniversalRegions<'tcx> {
+        self.universal_regions.as_ref()
+    }
+
+    /// Tries to find the best constraint to blame for the fact that
+    /// `R: from_region`, where `R` is some region that meets
+    /// `target_test`. This works by following the constraint graph,
+    /// creating a constraint path that forces `R` to outlive
+    /// `from_region`, and then finding the best choices within that
+    /// path to blame.
+    crate fn best_blame_constraint(
+        &self,
+        body: &Body<'tcx>,
+        from_region: RegionVid,
+        from_region_origin: NLLRegionVariableOrigin,
+        target_test: impl Fn(RegionVid) -> bool,
+    ) -> (ConstraintCategory, bool, Span) {
+        debug!(
+            "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
+            from_region, from_region_origin
+        );
+
+        // Find all paths
+        let (path, target_region) =
+            self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
+        debug!(
+            "best_blame_constraint: path={:#?}",
+            path.iter()
+                .map(|&c| format!(
+                    "{:?} ({:?}: {:?})",
+                    c,
+                    self.constraint_sccs.scc(c.sup),
+                    self.constraint_sccs.scc(c.sub),
+                ))
+                .collect::<Vec<_>>()
+        );
+
+        // Classify each of the constraints along the path.
+        let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
+            .iter()
+            .map(|constraint| {
+                if constraint.category == ConstraintCategory::ClosureBounds {
+                    self.retrieve_closure_constraint_info(body, &constraint)
+                } else {
+                    (constraint.category, false, constraint.locations.span(body))
+                }
+            })
+            .collect();
+        debug!("best_blame_constraint: categorized_path={:#?}", categorized_path);
+
+        // To find the best span to cite, we first try to look for the
+        // final constraint that is interesting and where the `sup` is
+        // not unified with the ultimate target region. The reason
+        // for this is that we have a chain of constraints that lead
+        // from the source to the target region, something like:
+        //
+        //    '0: '1 ('0 is the source)
+        //    '1: '2
+        //    '2: '3
+        //    '3: '4
+        //    '4: '5
+        //    '5: '6 ('6 is the target)
+        //
+        // Some of those regions are unified with `'6` (in the same
+        // SCC).  We want to screen those out. After that point, the
+        // "closest" constraint we have to the end is going to be the
+        // most likely to be the point where the value escapes -- but
+        // we still want to screen for an "interesting" point to
+        // highlight (e.g., a call site or something).
+        let target_scc = self.constraint_sccs.scc(target_region);
+        let mut range = 0..path.len();
+
+        // As noted above, when reporting an error, there is typically a chain of constraints
+        // leading from some "source" region which must outlive some "target" region.
+        // In most cases, we prefer to "blame" the constraints closer to the target --
+        // but there is one exception. When constraints arise from higher-ranked subtyping,
+        // we generally prefer to blame the source value,
+        // as the "target" in this case tends to be some type annotation that the user gave.
+        // Therefore, if we find that the region origin is some instantiation
+        // of a higher-ranked region, we start our search from the "source" point
+        // rather than the "target", and we also tweak a few other things.
+        //
+        // An example might be this bit of Rust code:
+        //
+        // ```rust
+        // let x: fn(&'static ()) = |_| {};
+        // let y: for<'a> fn(&'a ()) = x;
+        // ```
+        //
+        // In MIR, this will be converted into a combination of assignments and type ascriptions.
+        // In particular, the 'static is imposed through a type ascription:
+        //
+        // ```rust
+        // x = ...;
+        // AscribeUserType(x, fn(&'static ())
+        // y = x;
+        // ```
+        //
+        // We wind up ultimately with constraints like
+        //
+        // ```rust
+        // !a: 'temp1 // from the `y = x` statement
+        // 'temp1: 'temp2
+        // 'temp2: 'static // from the AscribeUserType
+        // ```
+        //
+        // and here we prefer to blame the source (the y = x statement).
+        let blame_source = match from_region_origin {
+            NLLRegionVariableOrigin::FreeRegion
+            | NLLRegionVariableOrigin::Existential { from_forall: false } => true,
+            NLLRegionVariableOrigin::Placeholder(_)
+            | NLLRegionVariableOrigin::Existential { from_forall: true } => false,
+        };
+
+        let find_region = |i: &usize| {
+            let constraint = path[*i];
+
+            let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
+
+            if blame_source {
+                match categorized_path[*i].0 {
+                    ConstraintCategory::OpaqueType
+                    | ConstraintCategory::Boring
+                    | ConstraintCategory::BoringNoLocation
+                    | ConstraintCategory::Internal => false,
+                    ConstraintCategory::TypeAnnotation
+                    | ConstraintCategory::Return
+                    | ConstraintCategory::Yield => true,
+                    _ => constraint_sup_scc != target_scc,
+                }
+            } else {
+                match categorized_path[*i].0 {
+                    ConstraintCategory::OpaqueType
+                    | ConstraintCategory::Boring
+                    | ConstraintCategory::BoringNoLocation
+                    | ConstraintCategory::Internal => false,
+                    _ => true,
+                }
+            }
+        };
+
+        let best_choice =
+            if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
+
+        debug!(
+            "best_blame_constraint: best_choice={:?} blame_source={}",
+            best_choice, blame_source
+        );
+
+        if let Some(i) = best_choice {
+            if let Some(next) = categorized_path.get(i + 1) {
+                if categorized_path[i].0 == ConstraintCategory::Return
+                    && next.0 == ConstraintCategory::OpaqueType
+                {
+                    // The return expression is being influenced by the return type being
+                    // impl Trait, point at the return type and not the return expr.
+                    return *next;
+                }
+            }
+            return categorized_path[i];
+        }
+
+        // If that search fails, that is.. unusual. Maybe everything
+        // is in the same SCC or something. In that case, find what
+        // appears to be the most interesting point to report to the
+        // user via an even more ad-hoc guess.
+        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
+        debug!("`: sorted_path={:#?}", categorized_path);
+
+        *categorized_path.first().unwrap()
+    }
 }
 
 impl<'tcx> RegionDefinition<'tcx> {
diff --git a/src/librustc_mir/borrow_check/region_infer/values.rs b/src/librustc_mir/borrow_check/region_infer/values.rs
index e17efeb..3126d44 100644
--- a/src/librustc_mir/borrow_check/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/region_infer/values.rs
@@ -114,7 +114,7 @@
 
 /// An individual element in a region value -- the value of a
 /// particular region variable consists of a set of these elements.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 crate enum RegionElement {
     /// A point in the control-flow graph.
     Location(Location),
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index a963735..c9a1c46 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -27,11 +27,12 @@
     TyCtxt, UserType, UserTypeAnnotationIndex,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::{Span, DUMMY_SP};
+use syntax::ast;
 
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::FlowAtLocation;
@@ -309,17 +310,54 @@
                 );
             }
         } else {
-            if let ty::ConstKind::Unevaluated(def_id, substs) = constant.literal.val {
-                if let Err(terr) = self.cx.fully_perform_op(
-                    location.to_locations(),
-                    ConstraintCategory::Boring,
-                    self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                        constant.literal.ty,
-                        def_id,
-                        UserSubsts { substs, user_self_ty: None },
-                    )),
-                ) {
-                    span_mirbug!(self, constant, "bad constant type {:?} ({:?})", constant, terr);
+            if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val {
+                if let Some(promoted) = promoted {
+                    let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
+                                     promoted: &ReadOnlyBodyAndCache<'_, 'tcx>,
+                                     ty,
+                                     san_ty| {
+                        if let Err(terr) = verifier.cx.eq_types(
+                            san_ty,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Boring,
+                        ) {
+                            span_mirbug!(
+                                verifier,
+                                promoted,
+                                "bad promoted type ({:?}: {:?}): {:?}",
+                                ty,
+                                san_ty,
+                                terr
+                            );
+                        };
+                    };
+
+                    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, &promoted_body, ty, promoted_ty);
+                    }
+                } else {
+                    if let Err(terr) = self.cx.fully_perform_op(
+                        location.to_locations(),
+                        ConstraintCategory::Boring,
+                        self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                            constant.literal.ty,
+                            def_id,
+                            UserSubsts { substs, user_self_ty: None },
+                        )),
+                    ) {
+                        span_mirbug!(
+                            self,
+                            constant,
+                            "bad constant type {:?} ({:?})",
+                            constant,
+                            terr
+                        );
+                    }
                 }
             }
             if let ty::FnDef(def_id, substs) = constant.literal.ty.kind {
@@ -427,83 +465,32 @@
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
 
-        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, def_id }) => {
-                let san_ty = self.sanitize_type(place, ty);
-                let check_err =
-                    |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, place: &Place<'tcx>, ty, san_ty| {
-                        if let Err(terr) = verifier.cx.eq_types(
-                            san_ty,
-                            ty,
-                            location.to_locations(),
-                            ConstraintCategory::Boring,
-                        ) {
-                            span_mirbug!(
-                                verifier,
-                                place,
-                                "bad promoted type ({:?}: {:?}): {:?}",
-                                ty,
-                                san_ty,
-                                terr
-                            );
-                        };
-                    };
-                match kind {
-                    StaticKind::Promoted(promoted, _) => {
-                        if !self.errors_reported {
-                            let promoted_body_cache = self.promoted[*promoted];
-                            self.sanitize_promoted(promoted_body_cache, location);
-
-                            let promoted_ty = promoted_body_cache.return_ty();
-                            check_err(self, place, promoted_ty, san_ty);
-                        }
-                    }
-                    StaticKind::Static => {
-                        let ty = self.tcx().type_of(*def_id);
-                        let ty = self.cx.normalize(ty, location);
-
-                        check_err(self, place, ty, san_ty);
-                    }
-                }
-                PlaceTy::from_ty(san_ty)
-            }
-        };
+        let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
 
         if place.projection.is_empty() {
             if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-                let is_promoted = match place.as_ref() {
-                    PlaceRef {
-                        base: &PlaceBase::Static(box Static { kind: StaticKind::Promoted(..), .. }),
-                        projection: &[],
-                    } => true,
-                    _ => false,
+                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, &[]),
-                    };
-
-                    // 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,
+                );
             }
         }
 
@@ -1944,12 +1931,15 @@
                                         traits::ObligationCauseCode::RepeatVec(should_suggest),
                                     ),
                                     self.param_env,
-                                    ty::Predicate::Trait(ty::Binder::bind(ty::TraitPredicate {
-                                        trait_ref: ty::TraitRef::new(
-                                            self.tcx().lang_items().copy_trait().unwrap(),
-                                            tcx.mk_substs_trait(ty, &[]),
-                                        ),
-                                    })),
+                                    ty::Predicate::Trait(
+                                        ty::Binder::bind(ty::TraitPredicate {
+                                            trait_ref: ty::TraitRef::new(
+                                                self.tcx().lang_items().copy_trait().unwrap(),
+                                                tcx.mk_substs_trait(ty, &[]),
+                                            ),
+                                        }),
+                                        ast::Constness::NotConst,
+                                    ),
                                 ),
                                 &traits::SelectionError::Unimplemented,
                                 false,
@@ -2400,7 +2390,7 @@
             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.local, proj_base, body, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.kind {
@@ -2587,7 +2577,10 @@
         category: ConstraintCategory,
     ) {
         self.prove_predicates(
-            Some(ty::Predicate::Trait(trait_ref.to_poly_trait_ref().to_poly_trait_predicate())),
+            Some(ty::Predicate::Trait(
+                trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
+                ast::Constness::NotConst,
+            )),
             locations,
             category,
         );
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index 608a243..5e4eebb 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -1,5 +1,5 @@
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind};
+use rustc::mir::{Local, Location, Place, Statement, StatementKind, TerminatorKind};
 
 use rustc_data_structures::fx::FxHashSet;
 
@@ -57,9 +57,7 @@
         // be those that were never initialized - we will consider those as being used as
         // they will either have been removed by unreachable code optimizations; or linted
         // as unused variables.
-        if let PlaceBase::Local(local) = into.base {
-            let _ = self.never_initialized_mut_locals.remove(&local);
-        }
+        self.never_initialized_mut_locals.remove(&into.local);
     }
 }
 
@@ -80,13 +78,11 @@
     fn visit_statement(&mut self, statement: &Statement<'tcx>, _location: Location) {
         match &statement.kind {
             StatementKind::Assign(box (into, _)) => {
-                if let PlaceBase::Local(local) = into.base {
-                    debug!(
-                        "visit_statement: statement={:?} local={:?} \
-                         never_initialized_mut_locals={:?}",
-                        statement, local, self.never_initialized_mut_locals
-                    );
-                }
+                debug!(
+                    "visit_statement: statement={:?} local={:?} \
+                    never_initialized_mut_locals={:?}",
+                    statement, into.local, self.never_initialized_mut_locals
+                );
                 self.remove_never_initialized_mut_locals(into);
             }
             _ => {}
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index ac04ae2..aad0e16 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -5,14 +5,16 @@
 use rustc::ty::{self, TyCtxt};
 use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
 
-use crate::interpret::{intern_const_alloc_recursive, ConstValue, InterpCx};
+use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
 
 mod error;
 mod eval_queries;
+mod fn_queries;
 mod machine;
 
 pub use error::*;
 pub use eval_queries::*;
+pub use fn_queries::*;
 pub use machine::*;
 
 /// Extracts a field of a (variant of a) const.
@@ -50,7 +52,7 @@
 
     let loc_ty = tcx.caller_location_ty();
     let loc_place = ecx.alloc_caller_location(file, line, col);
-    intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
+    intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
     let loc_const = ty::Const {
         ty: loc_ty,
         val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
@@ -59,15 +61,32 @@
     tcx.mk_const(loc_const)
 }
 
-// this function uses `unwrap` copiously, because an already validated constant must have valid
-// fields and can thus never fail outside of compiler bugs
-pub(crate) fn const_variant_index<'tcx>(
+// this function uses `unwrap` copiously, because an already validated constant
+// must have valid fields and can thus never fail outside of compiler bugs
+pub(crate) fn destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     val: &'tcx ty::Const<'tcx>,
-) -> VariantIdx {
-    trace!("const_variant_index: {:?}", val);
+) -> mir::DestructuredConst<'tcx> {
+    trace!("destructure_const: {:?}", val);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     let op = ecx.eval_const_to_op(val, None).unwrap();
-    ecx.read_discriminant(op).unwrap().1
+
+    let variant = ecx.read_discriminant(op).unwrap().1;
+
+    let field_count = match val.ty.kind {
+        ty::Array(_, len) => len.eval_usize(tcx, param_env),
+        ty::Adt(def, _) => def.variants[variant].fields.len() as u64,
+        ty::Tuple(substs) => substs.len() as u64,
+        _ => bug!("cannot destructure constant {:?}", val),
+    };
+
+    let down = ecx.operand_downcast(op, variant).unwrap();
+    let fields_iter = (0..field_count).map(|i| {
+        let field_op = ecx.operand_field(down, i).unwrap();
+        op_to_const(&ecx, field_op)
+    });
+    let fields = tcx.arena.alloc_from_iter(fields_iter);
+
+    mir::DestructuredConst { variant, fields }
 }
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index dbeb75b..442baf8 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -1,9 +1,9 @@
 use super::{error_to_const_error, CompileTimeEvalContext, CompileTimeInterpreter, MemoryExtra};
 use crate::interpret::eval_nullary_intrinsic;
 use crate::interpret::{
-    intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, ImmTy, Immediate, InterpCx,
-    InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar, ScalarMaybeUndef,
-    StackPopCleanup,
+    intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, ImmTy, Immediate, InternKind,
+    InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
+    ScalarMaybeUndef, StackPopCleanup,
 };
 use rustc::mir;
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
@@ -56,7 +56,17 @@
     ecx.run()?;
 
     // Intern the result
-    intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?;
+    let intern_kind = match tcx.static_mutability(cid.instance.def_id()) {
+        Some(m) => InternKind::Static(m),
+        None if cid.promoted.is_some() => InternKind::Promoted,
+        _ => InternKind::Constant,
+    };
+    intern_const_alloc_recursive(
+        ecx,
+        intern_kind,
+        ret,
+        body.ignore_interior_mut_in_const_validation,
+    )?;
 
     debug!("eval_body_using_ecx done: {:?}", *ret);
     Ok(ret)
@@ -115,28 +125,31 @@
         // by-val is if we are in const_field, i.e., if this is (a field of) something that we
         // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
         // structs containing such.
-        op.try_as_mplace()
+        op.try_as_mplace(ecx)
     };
-    let val = match immediate {
-        Ok(mplace) => {
-            let ptr = mplace.ptr.assert_ptr();
+
+    let to_const_value = |mplace: MPlaceTy<'_>| match mplace.ptr {
+        Scalar::Ptr(ptr) => {
             let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
             ConstValue::ByRef { alloc, offset: ptr.offset }
         }
+        Scalar::Raw { data, .. } => {
+            assert!(mplace.layout.is_zst());
+            assert_eq!(
+                data,
+                mplace.layout.align.abi.bytes().into(),
+                "this MPlaceTy must come from `try_as_mplace` being used on a zst, so we know what
+                 value this integer address must have",
+            );
+            ConstValue::Scalar(Scalar::zst())
+        }
+    };
+    let val = match immediate {
+        Ok(mplace) => to_const_value(mplace),
         // see comment on `let try_as_immediate` above
         Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
             ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
-            ScalarMaybeUndef::Undef => {
-                // When coming out of "normal CTFE", we'll always have an `Indirect` operand as
-                // argument and we will not need this. The only way we can already have an
-                // `Immediate` is when we are called from `const_field`, and that `Immediate`
-                // comes from a constant so it can happen have `Undef`, because the indirect
-                // memory that was read had undefined bytes.
-                let mplace = op.assert_mem_place();
-                let ptr = mplace.ptr.assert_ptr();
-                let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
-                ConstValue::ByRef { alloc, offset: ptr.offset }
-            }
+            ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
         },
         Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
             let (data, start) = match a.not_undef().unwrap() {
@@ -168,9 +181,14 @@
     let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static);
     let val = (|| {
         let mplace = ecx.raw_const_to_mplace(constant)?;
-        let mut ref_tracking = RefTracking::new(mplace);
-        while let Some((mplace, path)) = ref_tracking.todo.pop() {
-            ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?;
+
+        // FIXME do not validate promoteds until a decision on
+        // https://github.com/rust-lang/rust/issues/67465 is made
+        if cid.promoted.is_none() {
+            let mut ref_tracking = RefTracking::new(mplace);
+            while let Some((mplace, path)) = ref_tracking.todo.pop() {
+                ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?;
+            }
         }
         // Now that we validated, turn this into a proper constant.
         // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs
new file mode 100644
index 0000000..2443e1e
--- /dev/null
+++ b/src/librustc_mir/const_eval/fn_queries.rs
@@ -0,0 +1,151 @@
+use rustc::hir::map::blocks::FnLikeNode;
+use rustc::ty::query::Providers;
+use rustc::ty::TyCtxt;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::Symbol;
+use rustc_target::spec::abi::Abi;
+use syntax::attr;
+
+/// Whether the `def_id` counts as const fn in your current crate, considering all active
+/// feature gates
+pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    tcx.is_const_fn_raw(def_id)
+        && match is_unstable_const_fn(tcx, def_id) {
+            Some(feature_name) => {
+                // has a `rustc_const_unstable` attribute, check whether the user enabled the
+                // corresponding feature gate.
+                tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_name)
+            }
+            // functions without const stability are either stable user written
+            // const fn or the user is using feature gates and we thus don't
+            // care what they do
+            None => true,
+        }
+}
+
+/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
+pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
+    if tcx.is_const_fn_raw(def_id) {
+        let const_stab = tcx.lookup_const_stability(def_id)?;
+        if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
+    } else {
+        None
+    }
+}
+
+/// Returns `true` if this function must conform to `min_const_fn`
+pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    // Bail out if the signature doesn't contain `const`
+    if !tcx.is_const_fn_raw(def_id) {
+        return false;
+    }
+
+    if tcx.features().staged_api {
+        // In order for a libstd function to be considered min_const_fn
+        // it needs to be stable and have no `rustc_const_unstable` attribute.
+        match tcx.lookup_const_stability(def_id) {
+            // `rustc_const_unstable` functions don't need to conform.
+            Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
+            None => {
+                if let Some(stab) = tcx.lookup_stability(def_id) {
+                    if stab.level.is_stable() {
+                        tcx.sess.span_err(
+                            tcx.def_span(def_id),
+                            "stable const functions must have either `rustc_const_stable` or \
+                             `rustc_const_unstable` attribute",
+                        );
+                        // While we errored above, because we don't know if we need to conform, we
+                        // err on the "safe" side and require min_const_fn.
+                        true
+                    } else {
+                        // Unstable functions need not conform to min_const_fn.
+                        false
+                    }
+                } else {
+                    // Internal functions are forced to conform to min_const_fn.
+                    // Annotate the internal function with a const stability attribute if
+                    // you need to use unstable features.
+                    // Note: this is an arbitrary choice that does not affect stability or const
+                    // safety or anything, it just changes whether we need to annotate some
+                    // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
+                    true
+                }
+            }
+            // Everything else needs to conform, because it would be callable from
+            // other `min_const_fn` functions.
+            _ => true,
+        }
+    } else {
+        // users enabling the `const_fn` feature gate can do what they want
+        !tcx.features().const_fn
+    }
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+    /// Const evaluability whitelist is here to check evaluability at the
+    /// top level beforehand.
+    fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
+        match tcx.fn_sig(def_id).abi() {
+            Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
+                Some(tcx.lookup_const_stability(def_id).is_some())
+            }
+            _ => None,
+        }
+    }
+
+    /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
+    /// said intrinsic is on the whitelist for being const callable.
+    fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        let hir_id = tcx
+            .hir()
+            .as_local_hir_id(def_id)
+            .expect("Non-local call to local provider is_const_fn");
+
+        let node = tcx.hir().get(hir_id);
+
+        if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
+            whitelisted
+        } else if let Some(fn_like) = FnLikeNode::from_node(node) {
+            fn_like.constness() == hir::Constness::Const
+        } else if let hir::Node::Ctor(_) = node {
+            true
+        } else {
+            false
+        }
+    }
+
+    fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        is_const_fn(tcx, def_id)
+            && match tcx.lookup_const_stability(def_id) {
+                Some(stab) => {
+                    if cfg!(debug_assertions) && stab.promotable {
+                        let sig = tcx.fn_sig(def_id);
+                        assert_eq!(
+                            sig.unsafety(),
+                            hir::Unsafety::Normal,
+                            "don't mark const unsafe fns as promotable",
+                            // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
+                        );
+                    }
+                    stab.promotable
+                }
+                None => false,
+            }
+    }
+
+    fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        is_const_fn(tcx, def_id)
+            && tcx
+                .lookup_const_stability(def_id)
+                .map(|stab| stab.allow_const_fn_ptr)
+                .unwrap_or(false)
+    }
+
+    *providers = Providers {
+        is_const_fn_raw,
+        is_promotable_const_fn,
+        const_fn_is_allowed_fn_ptr,
+        ..*providers
+    };
+}
diff --git a/src/librustc_mir/dataflow/generic.rs b/src/librustc_mir/dataflow/generic.rs
deleted file mode 100644
index d2ca4f1..0000000
--- a/src/librustc_mir/dataflow/generic.rs
+++ /dev/null
@@ -1,595 +0,0 @@
-//! Dataflow analysis with arbitrary transfer functions.
-//!
-//! This module is a work in progress. You should instead use `BitDenotation` in
-//! `librustc_mir/dataflow/mod.rs` and encode your transfer function as a [gen/kill set][gk]. In
-//! doing so, your analysis will run faster and you will be able to generate graphviz diagrams for
-//! debugging with no extra effort. The interface in this module is intended only for dataflow
-//! problems that cannot be expressed using gen/kill sets.
-//!
-//! FIXME(ecstaticmorse): In the long term, the plan is to preserve the existing `BitDenotation`
-//! interface, but make `Engine` and `ResultsCursor` the canonical way to perform and inspect a
-//! dataflow analysis. This requires porting the graphviz debugging logic to this module, deciding
-//! on a way to handle the `before` methods in `BitDenotation` and creating an adapter so that
-//! gen-kill problems can still be evaluated efficiently. See the discussion in [#64566] for more
-//! information.
-//!
-//! [gk]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
-//! [#64566]: https://github.com/rust-lang/rust/pull/64566
-
-use std::borrow::Borrow;
-use std::cmp::Ordering;
-use std::ffi::OsString;
-use std::path::{Path, PathBuf};
-use std::{fs, io, ops};
-
-use rustc::mir::{self, traversal, BasicBlock, Location};
-use rustc::ty::{self, TyCtxt};
-use rustc_data_structures::work_queue::WorkQueue;
-use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
-use rustc_span::symbol::sym;
-
-use crate::dataflow::BottomValue;
-
-mod graphviz;
-
-/// A specific kind of dataflow analysis.
-///
-/// To run a dataflow analysis, one must set the initial state of the `START_BLOCK` via
-/// `initialize_start_block` and define a transfer function for each statement or terminator via
-/// the various `effect` methods. The entry set for all other basic blocks is initialized to
-/// `Self::BOTTOM_VALUE`. The dataflow `Engine` then iteratively updates the various entry sets for
-/// each block with the cumulative effects of the transfer functions of all preceding blocks.
-///
-/// You should use an `Engine` to actually run an analysis, and a `ResultsCursor` to inspect the
-/// results of that analysis like so:
-///
-/// ```ignore(cross-crate-imports)
-/// fn do_my_analysis(body: &mir::Body<'tcx>, dead_unwinds: &BitSet<BasicBlock>) {
-///     // `MyAnalysis` implements `Analysis`.
-///     let analysis = MyAnalysis::new();
-///
-///     let results = Engine::new(body, dead_unwinds, analysis).iterate_to_fixpoint();
-///     let mut cursor = ResultsCursor::new(body, results);
-///
-///     for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() {
-///         cursor.seek_after(Location { block: START_BLOCK, statement_index });
-///         let state = cursor.get();
-///         println!("{:?}", state);
-///     }
-/// }
-/// ```
-pub trait Analysis<'tcx>: BottomValue {
-    /// The index type used to access the dataflow state.
-    type Idx: Idx;
-
-    /// A name, used for debugging, that describes this dataflow analysis.
-    ///
-    /// The name should be suitable as part of a filename, so avoid whitespace, slashes or periods
-    /// and try to keep it short.
-    const NAME: &'static str;
-
-    /// How each element of your dataflow state will be displayed during debugging.
-    ///
-    /// By default, this is the `fmt::Debug` representation of `Self::Idx`.
-    fn pretty_print_idx(&self, w: &mut impl io::Write, idx: Self::Idx) -> io::Result<()> {
-        write!(w, "{:?}", idx)
-    }
-
-    /// The size of each bitvector allocated for each block.
-    fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize;
-
-    /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow
-    /// analysis.
-    fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>);
-
-    /// Updates the current dataflow state with the effect of evaluating a statement.
-    fn apply_statement_effect(
-        &self,
-        state: &mut BitSet<Self::Idx>,
-        statement: &mir::Statement<'tcx>,
-        location: Location,
-    );
-
-    /// Updates the current dataflow state with the effect of evaluating a terminator.
-    ///
-    /// Note that the effect of a successful return from a `Call` terminator should **not** be
-    /// acounted for in this function. That should go in `apply_call_return_effect`. For example,
-    /// in the `InitializedPlaces` analyses, the return place is not marked as initialized here.
-    fn apply_terminator_effect(
-        &self,
-        state: &mut BitSet<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
-        location: Location,
-    );
-
-    /// Updates the current dataflow state with the effect of a successful return from a `Call`
-    /// terminator.
-    ///
-    /// This is separated from `apply_terminator_effect` to properly track state across
-    /// unwind edges for `Call`s.
-    fn apply_call_return_effect(
-        &self,
-        state: &mut BitSet<Self::Idx>,
-        block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
-        return_place: &mir::Place<'tcx>,
-    );
-
-    /// Applies the cumulative effect of an entire basic block to the dataflow state (except for
-    /// `call_return_effect`, which is handled in the `Engine`).
-    ///
-    /// The default implementation calls `statement_effect` for every statement in the block before
-    /// finally calling `terminator_effect`. However, some dataflow analyses are able to coalesce
-    /// transfer functions for an entire block and apply them at once. Such analyses should
-    /// override `block_effect`.
-    fn apply_whole_block_effect(
-        &self,
-        state: &mut BitSet<Self::Idx>,
-        block: BasicBlock,
-        block_data: &mir::BasicBlockData<'tcx>,
-    ) {
-        for (statement_index, stmt) in block_data.statements.iter().enumerate() {
-            let location = Location { block, statement_index };
-            self.apply_statement_effect(state, stmt, location);
-        }
-
-        let location = Location { block, statement_index: block_data.statements.len() };
-        self.apply_terminator_effect(state, block_data.terminator(), location);
-    }
-
-    /// Applies the cumulative effect of a sequence of statements (and possibly a terminator)
-    /// within a single basic block.
-    ///
-    /// When called with `0..block_data.statements.len() + 1` as the statement range, this function
-    /// is equivalent to `apply_whole_block_effect`.
-    fn apply_partial_block_effect(
-        &self,
-        state: &mut BitSet<Self::Idx>,
-        block: BasicBlock,
-        block_data: &mir::BasicBlockData<'tcx>,
-        mut range: ops::Range<usize>,
-    ) {
-        if range.is_empty() {
-            return;
-        }
-
-        // The final location might be a terminator, so iterate through all statements until the
-        // final one, then check to see whether the final one is a statement or terminator.
-        //
-        // This can't cause the range to wrap-around since we check that the range contains at
-        // least one element above.
-        range.end -= 1;
-        let final_location = Location { block, statement_index: range.end };
-
-        for statement_index in range {
-            let location = Location { block, statement_index };
-            let stmt = &block_data.statements[statement_index];
-            self.apply_statement_effect(state, stmt, location);
-        }
-
-        if final_location.statement_index == block_data.statements.len() {
-            let terminator = block_data.terminator();
-            self.apply_terminator_effect(state, terminator, final_location);
-        } else {
-            let stmt = &block_data.statements[final_location.statement_index];
-            self.apply_statement_effect(state, stmt, final_location);
-        }
-    }
-}
-
-#[derive(Clone, Copy, Debug)]
-enum CursorPosition {
-    AtBlockStart(BasicBlock),
-    After(Location),
-}
-
-impl CursorPosition {
-    fn block(&self) -> BasicBlock {
-        match *self {
-            Self::AtBlockStart(block) => block,
-            Self::After(Location { block, .. }) => block,
-        }
-    }
-}
-
-type ResultsRefCursor<'a, 'mir, 'tcx, A> = ResultsCursor<'mir, 'tcx, A, &'a Results<'tcx, A>>;
-
-/// Inspect the results of dataflow analysis.
-///
-/// This cursor has linear performance when visiting statements in a block in order. Visiting
-/// statements within a block in reverse order is `O(n^2)`, where `n` is the number of statements
-/// in that block.
-pub struct ResultsCursor<'mir, 'tcx, A, R = Results<'tcx, A>>
-where
-    A: Analysis<'tcx>,
-{
-    body: &'mir mir::Body<'tcx>,
-    results: R,
-    state: BitSet<A::Idx>,
-
-    pos: CursorPosition,
-
-    /// Whether the effects of `apply_call_return_effect` are currently stored in `state`.
-    ///
-    /// This flag ensures that multiple calls to `seek_after_assume_call_returns` with the same
-    /// target only result in one invocation of `apply_call_return_effect`.
-    is_call_return_effect_applied: bool,
-}
-
-impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
-where
-    A: Analysis<'tcx>,
-    R: Borrow<Results<'tcx, A>>,
-{
-    /// Returns a new cursor for `results` that points to the start of the `START_BLOCK`.
-    pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
-        ResultsCursor {
-            body,
-            pos: CursorPosition::AtBlockStart(mir::START_BLOCK),
-            is_call_return_effect_applied: false,
-            state: results.borrow().entry_sets[mir::START_BLOCK].clone(),
-            results,
-        }
-    }
-
-    pub fn analysis(&self) -> &A {
-        &self.results.borrow().analysis
-    }
-
-    /// Resets the cursor to the start of the given `block`.
-    pub fn seek_to_block_start(&mut self, block: BasicBlock) {
-        self.state.overwrite(&self.results.borrow().entry_sets[block]);
-        self.pos = CursorPosition::AtBlockStart(block);
-        self.is_call_return_effect_applied = false;
-    }
-
-    /// Updates the cursor to hold the dataflow state immediately before `target`.
-    pub fn seek_before(&mut self, target: Location) {
-        assert!(target <= self.body.terminator_loc(target.block));
-
-        if target.statement_index == 0 {
-            self.seek_to_block_start(target.block);
-        } else {
-            self._seek_after(Location {
-                block: target.block,
-                statement_index: target.statement_index - 1,
-            });
-        }
-    }
-
-    /// Updates the cursor to hold the dataflow state at `target`.
-    ///
-    /// If `target` is a `Call` terminator, `apply_call_return_effect` will not be called. See
-    /// `seek_after_assume_call_returns` if you wish to observe the dataflow state upon a
-    /// successful return.
-    pub fn seek_after(&mut self, target: Location) {
-        assert!(target <= self.body.terminator_loc(target.block));
-
-        // This check ensures the correctness of a call to `seek_after_assume_call_returns`
-        // followed by one to `seek_after` with the same target.
-        if self.is_call_return_effect_applied {
-            self.seek_to_block_start(target.block);
-        }
-
-        self._seek_after(target);
-    }
-
-    /// Equivalent to `seek_after`, but also calls `apply_call_return_effect` if `target` is a
-    /// `Call` terminator whose callee is convergent.
-    pub fn seek_after_assume_call_returns(&mut self, target: Location) {
-        assert!(target <= self.body.terminator_loc(target.block));
-
-        self._seek_after(target);
-
-        if target != self.body.terminator_loc(target.block) {
-            return;
-        }
-
-        let term = self.body.basic_blocks()[target.block].terminator();
-        if let mir::TerminatorKind::Call {
-            destination: Some((return_place, _)), func, args, ..
-        } = &term.kind
-        {
-            if !self.is_call_return_effect_applied {
-                self.is_call_return_effect_applied = true;
-                self.results.borrow().analysis.apply_call_return_effect(
-                    &mut self.state,
-                    target.block,
-                    func,
-                    args,
-                    return_place,
-                );
-            }
-        }
-    }
-
-    fn _seek_after(&mut self, target: Location) {
-        let Location { block: target_block, statement_index: target_index } = target;
-
-        if self.pos.block() != target_block {
-            self.seek_to_block_start(target_block);
-        }
-
-        // If we're in the same block but after the target statement, we need to reset to the start
-        // of the block.
-        if let CursorPosition::After(Location { statement_index: curr_index, .. }) = self.pos {
-            match curr_index.cmp(&target_index) {
-                Ordering::Equal => return,
-                Ordering::Less => {}
-                Ordering::Greater => self.seek_to_block_start(target_block),
-            }
-        }
-
-        // The cursor is now in the same block as the target location pointing at an earlier
-        // statement.
-        debug_assert_eq!(self.pos.block(), target_block);
-        if let CursorPosition::After(Location { statement_index, .. }) = self.pos {
-            debug_assert!(statement_index < target_index);
-        }
-
-        let first_unapplied_statement = match self.pos {
-            CursorPosition::AtBlockStart(_) => 0,
-            CursorPosition::After(Location { statement_index, .. }) => statement_index + 1,
-        };
-
-        let block_data = &self.body.basic_blocks()[target_block];
-        self.results.borrow().analysis.apply_partial_block_effect(
-            &mut self.state,
-            target_block,
-            block_data,
-            first_unapplied_statement..target_index + 1,
-        );
-
-        self.pos = CursorPosition::After(target);
-        self.is_call_return_effect_applied = false;
-    }
-
-    /// Gets the dataflow state at the current location.
-    pub fn get(&self) -> &BitSet<A::Idx> {
-        &self.state
-    }
-}
-
-/// A completed dataflow analysis.
-pub struct Results<'tcx, A>
-where
-    A: Analysis<'tcx>,
-{
-    analysis: A,
-    entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
-}
-
-/// All information required to iterate a dataflow analysis to fixpoint.
-pub struct Engine<'a, 'tcx, A>
-where
-    A: Analysis<'tcx>,
-{
-    analysis: A,
-    bits_per_block: usize,
-    tcx: TyCtxt<'tcx>,
-    body: &'a mir::Body<'tcx>,
-    def_id: DefId,
-    dead_unwinds: &'a BitSet<BasicBlock>,
-    entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
-}
-
-impl<A> Engine<'a, 'tcx, A>
-where
-    A: Analysis<'tcx>,
-{
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        body: &'a mir::Body<'tcx>,
-        def_id: DefId,
-        dead_unwinds: &'a BitSet<BasicBlock>,
-        analysis: A,
-    ) -> Self {
-        let bits_per_block = analysis.bits_per_block(body);
-
-        let bottom_value_set = if A::BOTTOM_VALUE == true {
-            BitSet::new_filled(bits_per_block)
-        } else {
-            BitSet::new_empty(bits_per_block)
-        };
-
-        let mut entry_sets = IndexVec::from_elem(bottom_value_set, body.basic_blocks());
-        analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
-
-        Engine { analysis, bits_per_block, tcx, body, def_id, dead_unwinds, entry_sets }
-    }
-
-    pub fn iterate_to_fixpoint(mut self) -> Results<'tcx, A> {
-        let mut temp_state = BitSet::new_empty(self.bits_per_block);
-
-        let mut dirty_queue: WorkQueue<BasicBlock> =
-            WorkQueue::with_none(self.body.basic_blocks().len());
-
-        for (bb, _) in traversal::reverse_postorder(self.body) {
-            dirty_queue.insert(bb);
-        }
-
-        // Add blocks that are not reachable from START_BLOCK to the work queue. These blocks will
-        // be processed after the ones added above.
-        for bb in self.body.basic_blocks().indices() {
-            dirty_queue.insert(bb);
-        }
-
-        while let Some(bb) = dirty_queue.pop() {
-            let bb_data = &self.body[bb];
-            let on_entry = &self.entry_sets[bb];
-
-            temp_state.overwrite(on_entry);
-            self.analysis.apply_whole_block_effect(&mut temp_state, bb, bb_data);
-
-            self.propagate_bits_into_graph_successors_of(
-                &mut temp_state,
-                (bb, bb_data),
-                &mut dirty_queue,
-            );
-        }
-
-        let Engine { tcx, body, def_id, analysis, entry_sets, .. } = self;
-
-        let results = Results { analysis, entry_sets };
-
-        let attrs = tcx.get_attrs(def_id);
-        if let Some(path) = get_dataflow_graphviz_output_path(tcx, attrs, A::NAME) {
-            let result = write_dataflow_graphviz_results(body, def_id, &path, &results);
-            if let Err(e) = result {
-                warn!("Failed to write dataflow results to {}: {}", path.display(), e);
-            }
-        }
-
-        results
-    }
-
-    fn propagate_bits_into_graph_successors_of(
-        &mut self,
-        in_out: &mut BitSet<A::Idx>,
-        (bb, bb_data): (BasicBlock, &'a mir::BasicBlockData<'tcx>),
-        dirty_list: &mut WorkQueue<BasicBlock>,
-    ) {
-        match bb_data.terminator().kind {
-            mir::TerminatorKind::Return
-            | mir::TerminatorKind::Resume
-            | mir::TerminatorKind::Abort
-            | mir::TerminatorKind::GeneratorDrop
-            | mir::TerminatorKind::Unreachable => {}
-
-            mir::TerminatorKind::Goto { target }
-            | mir::TerminatorKind::Assert { target, cleanup: None, .. }
-            | mir::TerminatorKind::Yield { resume: target, drop: None, .. }
-            | mir::TerminatorKind::Drop { target, location: _, unwind: None }
-            | mir::TerminatorKind::DropAndReplace { target, value: _, location: _, unwind: None } =>
-            {
-                self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
-            }
-
-            mir::TerminatorKind::Yield { resume: target, drop: Some(drop), .. } => {
-                self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
-                self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
-            }
-
-            mir::TerminatorKind::Assert { target, cleanup: Some(unwind), .. }
-            | mir::TerminatorKind::Drop { target, location: _, unwind: Some(unwind) }
-            | mir::TerminatorKind::DropAndReplace {
-                target,
-                value: _,
-                location: _,
-                unwind: Some(unwind),
-            } => {
-                self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
-                if !self.dead_unwinds.contains(bb) {
-                    self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
-                }
-            }
-
-            mir::TerminatorKind::SwitchInt { ref targets, .. } => {
-                for target in targets {
-                    self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list);
-                }
-            }
-
-            mir::TerminatorKind::Call { cleanup, ref destination, ref func, ref args, .. } => {
-                if let Some(unwind) = cleanup {
-                    if !self.dead_unwinds.contains(bb) {
-                        self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
-                    }
-                }
-
-                if let Some((ref dest_place, dest_bb)) = *destination {
-                    // N.B.: This must be done *last*, after all other
-                    // propagation, as documented in comment above.
-                    self.analysis.apply_call_return_effect(in_out, bb, func, args, dest_place);
-                    self.propagate_bits_into_entry_set_for(in_out, dest_bb, dirty_list);
-                }
-            }
-
-            mir::TerminatorKind::FalseEdges { real_target, imaginary_target } => {
-                self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
-                self.propagate_bits_into_entry_set_for(in_out, imaginary_target, dirty_list);
-            }
-
-            mir::TerminatorKind::FalseUnwind { real_target, unwind } => {
-                self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
-                if let Some(unwind) = unwind {
-                    if !self.dead_unwinds.contains(bb) {
-                        self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
-                    }
-                }
-            }
-        }
-    }
-
-    fn propagate_bits_into_entry_set_for(
-        &mut self,
-        in_out: &BitSet<A::Idx>,
-        bb: BasicBlock,
-        dirty_queue: &mut WorkQueue<BasicBlock>,
-    ) {
-        let entry_set = &mut self.entry_sets[bb];
-        let set_changed = self.analysis.join(entry_set, &in_out);
-        if set_changed {
-            dirty_queue.insert(bb);
-        }
-    }
-}
-
-/// Looks for attributes like `#[rustc_mir(borrowck_graphviz_postflow="./path/to/suffix.dot")]` and
-/// extracts the path with the given analysis name prepended to the suffix.
-///
-/// Returns `None` if no such attribute exists.
-fn get_dataflow_graphviz_output_path(
-    tcx: TyCtxt<'tcx>,
-    attrs: ty::Attributes<'tcx>,
-    analysis: &str,
-) -> Option<PathBuf> {
-    let mut rustc_mir_attrs = attrs
-        .into_iter()
-        .filter(|attr| attr.check_name(sym::rustc_mir))
-        .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
-
-    let borrowck_graphviz_postflow =
-        rustc_mir_attrs.find(|attr| attr.check_name(sym::borrowck_graphviz_postflow))?;
-
-    let path_and_suffix = match borrowck_graphviz_postflow.value_str() {
-        Some(p) => p,
-        None => {
-            tcx.sess.span_err(
-                borrowck_graphviz_postflow.span(),
-                "borrowck_graphviz_postflow requires a path",
-            );
-
-            return None;
-        }
-    };
-
-    // Change "path/suffix.dot" to "path/analysis_name_suffix.dot"
-    let mut ret = PathBuf::from(path_and_suffix.to_string());
-    let suffix = ret.file_name().unwrap();
-
-    let mut file_name: OsString = analysis.into();
-    file_name.push("_");
-    file_name.push(suffix);
-    ret.set_file_name(file_name);
-
-    Some(ret)
-}
-
-fn write_dataflow_graphviz_results<A: Analysis<'tcx>>(
-    body: &mir::Body<'tcx>,
-    def_id: DefId,
-    path: &Path,
-    results: &Results<'tcx, A>,
-) -> io::Result<()> {
-    debug!("printing dataflow results for {:?} to {}", def_id, path.display());
-
-    let mut buf = Vec::new();
-    let graphviz = graphviz::Formatter::new(body, def_id, results);
-
-    dot::render(&graphviz, &mut buf)?;
-    fs::write(path, buf)
-}
diff --git a/src/librustc_mir/dataflow/generic/cursor.rs b/src/librustc_mir/dataflow/generic/cursor.rs
new file mode 100644
index 0000000..d2eff49
--- /dev/null
+++ b/src/librustc_mir/dataflow/generic/cursor.rs
@@ -0,0 +1,265 @@
+//! Random access inspection of the results of a dataflow analysis.
+
+use std::borrow::Borrow;
+
+use rustc::mir::{self, BasicBlock, Location};
+use rustc_index::bit_set::BitSet;
+
+use super::{Analysis, Results};
+
+/// A `ResultsCursor` that borrows the underlying `Results`.
+pub type ResultsRefCursor<'a, 'mir, 'tcx, A> = ResultsCursor<'mir, 'tcx, A, &'a Results<'tcx, A>>;
+
+/// Allows random access inspection of the results of a dataflow analysis.
+///
+/// This cursor only has linear performance within a basic block when its statements are visited in
+/// order. In the worst case—when statements are visited in *reverse* order—performance will be
+/// quadratic in the number of statements in the block. The order in which basic blocks are
+/// inspected has no impact on performance.
+///
+/// A `ResultsCursor` can either own (the default) or borrow the dataflow results it inspects. The
+/// type of ownership is determined by `R` (see `ResultsRefCursor` above).
+pub struct ResultsCursor<'mir, 'tcx, A, R = Results<'tcx, A>>
+where
+    A: Analysis<'tcx>,
+{
+    body: &'mir mir::Body<'tcx>,
+    results: R,
+    state: BitSet<A::Idx>,
+
+    pos: CursorPosition,
+
+    /// When this flag is set, the cursor is pointing at a `Call` terminator whose call return
+    /// effect has been applied to `state`.
+    ///
+    /// This flag helps to ensure that multiple calls to `seek_after_assume_call_returns` with the
+    /// same target will result in exactly one invocation of `apply_call_return_effect`. It is
+    /// sufficient to clear this only in `seek_to_block_start`, since seeking away from a
+    /// terminator will always require a cursor reset.
+    call_return_effect_applied: bool,
+}
+
+impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
+where
+    A: Analysis<'tcx>,
+    R: Borrow<Results<'tcx, A>>,
+{
+    /// Returns a new cursor for `results` that points to the start of the `START_BLOCK`.
+    pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
+        ResultsCursor {
+            body,
+            pos: CursorPosition::BlockStart(mir::START_BLOCK),
+            state: results.borrow().entry_sets[mir::START_BLOCK].clone(),
+            call_return_effect_applied: false,
+            results,
+        }
+    }
+
+    /// Returns the `Analysis` used to generate the underlying results.
+    pub fn analysis(&self) -> &A {
+        &self.results.borrow().analysis
+    }
+
+    /// Returns the dataflow state at the current location.
+    pub fn get(&self) -> &BitSet<A::Idx> {
+        &self.state
+    }
+
+    /// Resets the cursor to the start of the given basic block.
+    pub fn seek_to_block_start(&mut self, block: BasicBlock) {
+        self.state.overwrite(&self.results.borrow().entry_sets[block]);
+        self.pos = CursorPosition::BlockStart(block);
+        self.call_return_effect_applied = false;
+    }
+
+    /// Advances the cursor to hold all effects up to and including to the "before" effect of the
+    /// statement (or terminator) at the given location.
+    ///
+    /// If you wish to observe the full effect of a statement or terminator, not just the "before"
+    /// effect, use `seek_after` or `seek_after_assume_call_returns`.
+    pub fn seek_before(&mut self, target: Location) {
+        assert!(target <= self.body.terminator_loc(target.block));
+        self.seek_(target, false);
+    }
+
+    /// Advances the cursor to hold the full effect of all statements (and possibly closing
+    /// terminators) up to and including the `target`.
+    ///
+    /// If the `target` is a `Call` terminator, any call return effect for that terminator will
+    /// **not** be observed. Use `seek_after_assume_call_returns` if you wish to observe the call
+    /// return effect.
+    pub fn seek_after(&mut self, target: Location) {
+        assert!(target <= self.body.terminator_loc(target.block));
+
+        // If we have already applied the call return effect, we are currently pointing at a `Call`
+        // terminator. Unconditionally reset the dataflow cursor, since there is no way to "undo"
+        // the call return effect.
+        if self.call_return_effect_applied {
+            self.seek_to_block_start(target.block);
+        }
+
+        self.seek_(target, true);
+    }
+
+    /// Advances the cursor to hold all effects up to and including of the statement (or
+    /// terminator) at the given location.
+    ///
+    /// If the `target` is a `Call` terminator, any call return effect for that terminator will
+    /// be observed. Use `seek_after` if you do **not** wish to observe the call return effect.
+    pub fn seek_after_assume_call_returns(&mut self, target: Location) {
+        let terminator_loc = self.body.terminator_loc(target.block);
+        assert!(target.statement_index <= terminator_loc.statement_index);
+
+        self.seek_(target, true);
+
+        if target != terminator_loc {
+            return;
+        }
+
+        let terminator = self.body.basic_blocks()[target.block].terminator();
+        if let mir::TerminatorKind::Call {
+            destination: Some((return_place, _)), func, args, ..
+        } = &terminator.kind
+        {
+            if !self.call_return_effect_applied {
+                self.call_return_effect_applied = true;
+                self.results.borrow().analysis.apply_call_return_effect(
+                    &mut self.state,
+                    target.block,
+                    func,
+                    args,
+                    return_place,
+                );
+            }
+        }
+    }
+
+    fn seek_(&mut self, target: Location, apply_after_effect_at_target: bool) {
+        use CursorPosition::*;
+
+        match self.pos {
+            // Return early if we are already at the target location.
+            Before(curr) if curr == target && !apply_after_effect_at_target => return,
+            After(curr) if curr == target && apply_after_effect_at_target => return,
+
+            // Otherwise, we must reset to the start of the target block if...
+
+            // we are in a different block entirely.
+            BlockStart(block) | Before(Location { block, .. }) | After(Location { block, .. })
+                if block != target.block =>
+            {
+                self.seek_to_block_start(target.block)
+            }
+
+            // we are in the same block but have advanced past the target statement.
+            Before(curr) | After(curr) if curr.statement_index > target.statement_index => {
+                self.seek_to_block_start(target.block)
+            }
+
+            // we have already applied the entire effect of a statement but only wish to observe
+            // its "before" effect.
+            After(curr)
+                if curr.statement_index == target.statement_index
+                    && !apply_after_effect_at_target =>
+            {
+                self.seek_to_block_start(target.block)
+            }
+
+            // N.B., `call_return_effect_applied` is checked in `seek_after`, not here.
+            _ => (),
+        }
+
+        let analysis = &self.results.borrow().analysis;
+        let block_data = &self.body.basic_blocks()[target.block];
+
+        // At this point, the cursor is in the same block as the target location at an earlier
+        // statement.
+        debug_assert_eq!(target.block, self.pos.block());
+
+        // Find the first statement whose transfer function has not yet been applied.
+        let first_unapplied_statement = match self.pos {
+            BlockStart(_) => 0,
+            After(Location { statement_index, .. }) => statement_index + 1,
+
+            // If we have only applied the "before" effect for the current statement, apply the
+            // remainder before continuing.
+            Before(curr) => {
+                if curr.statement_index == block_data.statements.len() {
+                    let terminator = block_data.terminator();
+                    analysis.apply_terminator_effect(&mut self.state, terminator, curr);
+                } else {
+                    let statement = &block_data.statements[curr.statement_index];
+                    analysis.apply_statement_effect(&mut self.state, statement, curr);
+                }
+
+                // If all we needed to do was go from `Before` to `After` in the same statement,
+                // we are now done.
+                if curr.statement_index == target.statement_index {
+                    debug_assert!(apply_after_effect_at_target);
+                    self.pos = After(target);
+                    return;
+                }
+
+                curr.statement_index + 1
+            }
+        };
+
+        // We have now applied all effects prior to `first_unapplied_statement`.
+
+        // Apply the effects of all statements before `target`.
+        let mut location = Location { block: target.block, statement_index: 0 };
+        for statement_index in first_unapplied_statement..target.statement_index {
+            location.statement_index = statement_index;
+            let statement = &block_data.statements[statement_index];
+            analysis.apply_before_statement_effect(&mut self.state, statement, location);
+            analysis.apply_statement_effect(&mut self.state, statement, location);
+        }
+
+        // Apply the effect of the statement (or terminator) at `target`.
+        location.statement_index = target.statement_index;
+        if target.statement_index == block_data.statements.len() {
+            let terminator = &block_data.terminator();
+            analysis.apply_before_terminator_effect(&mut self.state, terminator, location);
+
+            if apply_after_effect_at_target {
+                analysis.apply_terminator_effect(&mut self.state, terminator, location);
+                self.pos = After(target);
+            } else {
+                self.pos = Before(target);
+            }
+        } else {
+            let statement = &block_data.statements[target.statement_index];
+            analysis.apply_before_statement_effect(&mut self.state, statement, location);
+
+            if apply_after_effect_at_target {
+                analysis.apply_statement_effect(&mut self.state, statement, location);
+                self.pos = After(target)
+            } else {
+                self.pos = Before(target);
+            }
+        }
+    }
+}
+
+#[derive(Clone, Copy, Debug)]
+enum CursorPosition {
+    /// No effects within this block have been applied.
+    BlockStart(BasicBlock),
+
+    /// Only the "before" effect of the statement (or terminator) at this location has been
+    /// applied (along with the effects of all previous statements).
+    Before(Location),
+
+    /// The effects of all statements up to and including the one at this location have been
+    /// applied.
+    After(Location),
+}
+
+impl CursorPosition {
+    fn block(&self) -> BasicBlock {
+        match *self {
+            Self::BlockStart(block) => block,
+            Self::Before(loc) | Self::After(loc) => loc.block,
+        }
+    }
+}
diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs
new file mode 100644
index 0000000..c0152b0
--- /dev/null
+++ b/src/librustc_mir/dataflow/generic/engine.rs
@@ -0,0 +1,427 @@
+//! A solver for dataflow problems.
+
+use std::ffi::OsString;
+use std::fs;
+use std::path::PathBuf;
+
+use rustc::mir::{self, traversal, BasicBlock, Location};
+use rustc::ty::TyCtxt;
+use rustc_data_structures::work_queue::WorkQueue;
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::IndexVec;
+use rustc_span::symbol::{sym, Symbol};
+use syntax::ast;
+
+use super::graphviz;
+use super::{Analysis, GenKillAnalysis, GenKillSet, Results};
+
+/// A solver for dataflow problems.
+pub struct Engine<'a, 'tcx, A>
+where
+    A: Analysis<'tcx>,
+{
+    bits_per_block: usize,
+    tcx: TyCtxt<'tcx>,
+    body: &'a mir::Body<'tcx>,
+    def_id: DefId,
+    dead_unwinds: Option<&'a BitSet<BasicBlock>>,
+    entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
+    analysis: A,
+
+    /// Cached, cumulative transfer functions for each block.
+    trans_for_block: Option<IndexVec<BasicBlock, GenKillSet<A::Idx>>>,
+}
+
+impl<A> Engine<'a, 'tcx, A>
+where
+    A: GenKillAnalysis<'tcx>,
+{
+    /// Creates a new `Engine` to solve a gen-kill dataflow problem.
+    pub fn new_gen_kill(
+        tcx: TyCtxt<'tcx>,
+        body: &'a mir::Body<'tcx>,
+        def_id: DefId,
+        analysis: A,
+    ) -> Self {
+        let bits_per_block = analysis.bits_per_block(body);
+        let mut trans_for_block =
+            IndexVec::from_elem(GenKillSet::identity(bits_per_block), body.basic_blocks());
+
+        // Compute cumulative block transfer functions.
+        //
+        // FIXME: we may want to skip this if the MIR is acyclic, since we will never access a
+        // block transfer function more than once.
+
+        for (block, block_data) in body.basic_blocks().iter_enumerated() {
+            let trans = &mut trans_for_block[block];
+
+            for (i, statement) in block_data.statements.iter().enumerate() {
+                let loc = Location { block, statement_index: i };
+                analysis.before_statement_effect(trans, statement, loc);
+                analysis.statement_effect(trans, statement, loc);
+            }
+
+            if let Some(terminator) = &block_data.terminator {
+                let loc = Location { block, statement_index: block_data.statements.len() };
+                analysis.before_terminator_effect(trans, terminator, loc);
+                analysis.terminator_effect(trans, terminator, loc);
+            }
+        }
+
+        Self::new(tcx, body, def_id, analysis, Some(trans_for_block))
+    }
+}
+
+impl<A> Engine<'a, 'tcx, A>
+where
+    A: Analysis<'tcx>,
+{
+    /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer
+    /// function.
+    ///
+    /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for
+    /// better performance.
+    pub fn new_generic(
+        tcx: TyCtxt<'tcx>,
+        body: &'a mir::Body<'tcx>,
+        def_id: DefId,
+        analysis: A,
+    ) -> Self {
+        Self::new(tcx, body, def_id, analysis, None)
+    }
+
+    fn new(
+        tcx: TyCtxt<'tcx>,
+        body: &'a mir::Body<'tcx>,
+        def_id: DefId,
+        analysis: A,
+        trans_for_block: Option<IndexVec<BasicBlock, GenKillSet<A::Idx>>>,
+    ) -> Self {
+        let bits_per_block = analysis.bits_per_block(body);
+
+        let bottom_value_set = if A::BOTTOM_VALUE == true {
+            BitSet::new_filled(bits_per_block)
+        } else {
+            BitSet::new_empty(bits_per_block)
+        };
+
+        let mut entry_sets = IndexVec::from_elem(bottom_value_set, body.basic_blocks());
+        analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
+
+        Engine {
+            analysis,
+            bits_per_block,
+            tcx,
+            body,
+            def_id,
+            dead_unwinds: None,
+            entry_sets,
+            trans_for_block,
+        }
+    }
+
+    /// Signals that we do not want dataflow state to propagate across unwind edges for these
+    /// `BasicBlock`s.
+    ///
+    /// You must take care that `dead_unwinds` does not contain a `BasicBlock` that *can* actually
+    /// unwind during execution. Otherwise, your dataflow results will not be correct.
+    pub fn dead_unwinds(mut self, dead_unwinds: &'a BitSet<BasicBlock>) -> Self {
+        self.dead_unwinds = Some(dead_unwinds);
+        self
+    }
+
+    /// Computes the fixpoint for this dataflow problem and returns it.
+    pub fn iterate_to_fixpoint(mut self) -> Results<'tcx, A> {
+        let mut temp_state = BitSet::new_empty(self.bits_per_block);
+
+        let mut dirty_queue: WorkQueue<BasicBlock> =
+            WorkQueue::with_none(self.body.basic_blocks().len());
+
+        for (bb, _) in traversal::reverse_postorder(self.body) {
+            dirty_queue.insert(bb);
+        }
+
+        // Add blocks that are not reachable from START_BLOCK to the work queue. These blocks will
+        // be processed after the ones added above.
+        for bb in self.body.basic_blocks().indices() {
+            dirty_queue.insert(bb);
+        }
+
+        while let Some(bb) = dirty_queue.pop() {
+            let bb_data = &self.body[bb];
+            let on_entry = &self.entry_sets[bb];
+
+            temp_state.overwrite(on_entry);
+            self.apply_whole_block_effect(&mut temp_state, bb, bb_data);
+
+            self.propagate_bits_into_graph_successors_of(
+                &mut temp_state,
+                (bb, bb_data),
+                &mut dirty_queue,
+            );
+        }
+
+        let Engine { tcx, body, def_id, trans_for_block, entry_sets, analysis, .. } = self;
+        let results = Results { analysis, entry_sets };
+
+        let res = write_graphviz_results(tcx, def_id, body, &results, trans_for_block);
+        if let Err(e) = res {
+            warn!("Failed to write graphviz dataflow results: {}", e);
+        }
+
+        results
+    }
+
+    /// Applies the cumulative effect of an entire block, excluding the call return effect if one
+    /// exists.
+    fn apply_whole_block_effect(
+        &self,
+        state: &mut BitSet<A::Idx>,
+        block: BasicBlock,
+        block_data: &mir::BasicBlockData<'tcx>,
+    ) {
+        // Use the cached block transfer function if available.
+        if let Some(trans_for_block) = &self.trans_for_block {
+            trans_for_block[block].apply(state);
+            return;
+        }
+
+        // Otherwise apply effects one-by-one.
+
+        for (statement_index, statement) in block_data.statements.iter().enumerate() {
+            let location = Location { block, statement_index };
+            self.analysis.apply_before_statement_effect(state, statement, location);
+            self.analysis.apply_statement_effect(state, statement, location);
+        }
+
+        let terminator = block_data.terminator();
+        let location = Location { block, statement_index: block_data.statements.len() };
+        self.analysis.apply_before_terminator_effect(state, terminator, location);
+        self.analysis.apply_terminator_effect(state, terminator, location);
+    }
+
+    fn propagate_bits_into_graph_successors_of(
+        &mut self,
+        in_out: &mut BitSet<A::Idx>,
+        (bb, bb_data): (BasicBlock, &'a mir::BasicBlockData<'tcx>),
+        dirty_list: &mut WorkQueue<BasicBlock>,
+    ) {
+        use mir::TerminatorKind::*;
+
+        match bb_data.terminator().kind {
+            Return | Resume | Abort | GeneratorDrop | Unreachable => {}
+
+            Goto { target }
+            | Assert { target, cleanup: None, .. }
+            | Yield { resume: target, drop: None, .. }
+            | Drop { target, location: _, unwind: None }
+            | DropAndReplace { target, value: _, location: _, unwind: None } => {
+                self.propagate_bits_into_entry_set_for(in_out, target, dirty_list)
+            }
+
+            Yield { resume: target, drop: Some(drop), .. } => {
+                self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+                self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
+            }
+
+            Assert { target, cleanup: Some(unwind), .. }
+            | Drop { target, location: _, unwind: Some(unwind) }
+            | DropAndReplace { target, value: _, location: _, unwind: Some(unwind) } => {
+                self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+                if self.dead_unwinds.map_or(true, |bbs| !bbs.contains(bb)) {
+                    self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+                }
+            }
+
+            SwitchInt { ref targets, .. } => {
+                for target in targets {
+                    self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list);
+                }
+            }
+
+            Call { cleanup, ref destination, ref func, ref args, .. } => {
+                if let Some(unwind) = cleanup {
+                    if self.dead_unwinds.map_or(true, |bbs| !bbs.contains(bb)) {
+                        self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+                    }
+                }
+
+                if let Some((ref dest_place, dest_bb)) = *destination {
+                    // N.B.: This must be done *last*, otherwise the unwind path will see the call
+                    // return effect.
+                    self.analysis.apply_call_return_effect(in_out, bb, func, args, dest_place);
+                    self.propagate_bits_into_entry_set_for(in_out, dest_bb, dirty_list);
+                }
+            }
+
+            FalseEdges { real_target, imaginary_target } => {
+                self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
+                self.propagate_bits_into_entry_set_for(in_out, imaginary_target, dirty_list);
+            }
+
+            FalseUnwind { real_target, unwind } => {
+                self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
+                if let Some(unwind) = unwind {
+                    if self.dead_unwinds.map_or(true, |bbs| !bbs.contains(bb)) {
+                        self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+                    }
+                }
+            }
+        }
+    }
+
+    fn propagate_bits_into_entry_set_for(
+        &mut self,
+        in_out: &BitSet<A::Idx>,
+        bb: BasicBlock,
+        dirty_queue: &mut WorkQueue<BasicBlock>,
+    ) {
+        let entry_set = &mut self.entry_sets[bb];
+        let set_changed = self.analysis.join(entry_set, &in_out);
+        if set_changed {
+            dirty_queue.insert(bb);
+        }
+    }
+}
+
+// Graphviz
+
+/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
+/// `rustc_mir` attributes.
+fn write_graphviz_results<A>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    body: &mir::Body<'tcx>,
+    results: &Results<'tcx, A>,
+    block_transfer_functions: Option<IndexVec<BasicBlock, GenKillSet<A::Idx>>>,
+) -> std::io::Result<()>
+where
+    A: Analysis<'tcx>,
+{
+    let attrs = match RustcMirAttrs::parse(tcx, def_id) {
+        Ok(attrs) => attrs,
+
+        // Invalid `rustc_mir` attrs will be reported using `span_err`.
+        Err(()) => return Ok(()),
+    };
+
+    let path = match attrs.output_path(A::NAME) {
+        Some(path) => path,
+        None => return Ok(()),
+    };
+
+    let bits_per_block = results.analysis.bits_per_block(body);
+
+    let mut formatter: Box<dyn graphviz::StateFormatter<'tcx, _>> = match attrs.formatter {
+        Some(sym::two_phase) => Box::new(graphviz::TwoPhaseDiff::new(bits_per_block)),
+        Some(sym::gen_kill) => {
+            if let Some(trans_for_block) = block_transfer_functions {
+                Box::new(graphviz::BlockTransferFunc::new(body, trans_for_block))
+            } else {
+                Box::new(graphviz::SimpleDiff::new(bits_per_block))
+            }
+        }
+
+        // Default to the `SimpleDiff` output style.
+        _ => Box::new(graphviz::SimpleDiff::new(bits_per_block)),
+    };
+
+    debug!("printing dataflow results for {:?} to {}", def_id, path.display());
+    let mut buf = Vec::new();
+
+    let graphviz = graphviz::Formatter::new(body, def_id, results, &mut *formatter);
+    dot::render(&graphviz, &mut buf)?;
+    fs::write(&path, buf)?;
+    Ok(())
+}
+
+#[derive(Default)]
+struct RustcMirAttrs {
+    basename_and_suffix: Option<PathBuf>,
+    formatter: Option<Symbol>,
+}
+
+impl RustcMirAttrs {
+    fn parse(tcx: TyCtxt<'tcx>, def_id: DefId) -> Result<Self, ()> {
+        let attrs = tcx.get_attrs(def_id);
+
+        let mut result = Ok(());
+        let mut ret = RustcMirAttrs::default();
+
+        let rustc_mir_attrs = attrs
+            .into_iter()
+            .filter(|attr| attr.check_name(sym::rustc_mir))
+            .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
+
+        for attr in rustc_mir_attrs {
+            let attr_result = if attr.check_name(sym::borrowck_graphviz_postflow) {
+                Self::set_field(&mut ret.basename_and_suffix, tcx, &attr, |s| {
+                    let path = PathBuf::from(s.to_string());
+                    match path.file_name() {
+                        Some(_) => Ok(path),
+                        None => {
+                            tcx.sess.span_err(attr.span(), "path must end in a filename");
+                            Err(())
+                        }
+                    }
+                })
+            } else if attr.check_name(sym::borrowck_graphviz_format) {
+                Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s {
+                    sym::gen_kill | sym::two_phase => Ok(s),
+                    _ => {
+                        tcx.sess.span_err(attr.span(), "unknown formatter");
+                        Err(())
+                    }
+                })
+            } else {
+                Ok(())
+            };
+
+            result = result.and(attr_result);
+        }
+
+        result.map(|()| ret)
+    }
+
+    fn set_field<T>(
+        field: &mut Option<T>,
+        tcx: TyCtxt<'tcx>,
+        attr: &ast::NestedMetaItem,
+        mapper: impl FnOnce(Symbol) -> Result<T, ()>,
+    ) -> Result<(), ()> {
+        if field.is_some() {
+            tcx.sess
+                .span_err(attr.span(), &format!("duplicate values for `{}`", attr.name_or_empty()));
+
+            return Err(());
+        }
+
+        if let Some(s) = attr.value_str() {
+            *field = Some(mapper(s)?);
+            Ok(())
+        } else {
+            tcx.sess
+                .span_err(attr.span(), &format!("`{}` requires an argument", attr.name_or_empty()));
+            Err(())
+        }
+    }
+
+    /// Returns the path where dataflow results should be written, or `None`
+    /// `borrowck_graphviz_postflow` was not specified.
+    ///
+    /// This performs the following transformation to the argument of `borrowck_graphviz_postflow`:
+    ///
+    /// "path/suffix.dot" -> "path/analysis_name_suffix.dot"
+    fn output_path(&self, analysis_name: &str) -> Option<PathBuf> {
+        let mut ret = self.basename_and_suffix.as_ref().cloned()?;
+        let suffix = ret.file_name().unwrap(); // Checked when parsing attrs
+
+        let mut file_name: OsString = analysis_name.into();
+        file_name.push("_");
+        file_name.push(suffix);
+        ret.set_file_name(file_name);
+
+        Some(ret)
+    }
+}
diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs
index e843956..fdf86e7 100644
--- a/src/librustc_mir/dataflow/generic/graphviz.rs
+++ b/src/librustc_mir/dataflow/generic/graphviz.rs
@@ -1,13 +1,14 @@
+//! A helpful diagram for debugging dataflow problems.
+
 use std::cell::RefCell;
-use std::io::{self, Write};
-use std::{ops, str};
+use std::{io, ops, str};
 
 use rustc::mir::{self, BasicBlock, Body, Location};
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::{BitSet, HybridBitSet};
-use rustc_index::vec::Idx;
+use rustc_index::vec::{Idx, IndexVec};
 
-use super::{Analysis, Results, ResultsRefCursor};
+use super::{Analysis, GenKillSet, Results, ResultsRefCursor};
 use crate::util::graphviz_safe_def_name;
 
 pub struct Formatter<'a, 'tcx, A>
@@ -25,11 +26,16 @@
 where
     A: Analysis<'tcx>,
 {
-    pub fn new(body: &'a Body<'tcx>, def_id: DefId, results: &'a Results<'tcx, A>) -> Self {
+    pub fn new(
+        body: &'a Body<'tcx>,
+        def_id: DefId,
+        results: &'a Results<'tcx, A>,
+        state_formatter: &'a mut dyn StateFormatter<'tcx, A>,
+    ) -> Self {
         let block_formatter = BlockFormatter {
             bg: Background::Light,
-            prev_state: BitSet::new_empty(results.analysis.bits_per_block(body)),
             results: ResultsRefCursor::new(body, results),
+            state_formatter,
         };
 
         Formatter { body, def_id, block_formatter: RefCell::new(block_formatter) }
@@ -117,15 +123,21 @@
 where
     A: Analysis<'tcx>,
 {
-    prev_state: BitSet<A::Idx>,
     results: ResultsRefCursor<'a, 'a, 'tcx, A>,
     bg: Background,
+    state_formatter: &'a mut dyn StateFormatter<'tcx, A>,
 }
 
 impl<A> BlockFormatter<'a, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
+    const HEADER_COLOR: &'static str = "#a0a0a0";
+
+    fn num_state_columns(&self) -> usize {
+        std::cmp::max(1, self.state_formatter.column_names().len())
+    }
+
     fn toggle_background(&mut self) -> Background {
         let bg = self.bg;
         self.bg = !bg;
@@ -164,196 +176,470 @@
             r#"<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb">"#,
         )?;
 
-        // A: Block info
-        write!(
-            w,
-            r#"<tr>
-                 <td colspan="{num_headers}" sides="tl">bb{block_id}</td>
-               </tr>"#,
-            num_headers = 3,
-            block_id = block.index(),
-        )?;
-
-        // B: Column headings
-        write!(
-            w,
-            r#"<tr>
-                 <td colspan="2" {fmt}>MIR</td>
-                 <td {fmt}>STATE</td>
-               </tr>"#,
-            fmt = r##"bgcolor="#a0a0a0" sides="tl""##,
-        )?;
+        // A + B: Block header
+        if self.state_formatter.column_names().is_empty() {
+            self.write_block_header_simple(w, block)?;
+        } else {
+            self.write_block_header_with_state_columns(w, block)?;
+        }
 
         // C: Entry state
         self.bg = Background::Light;
         self.results.seek_to_block_start(block);
-        self.write_row_with_curr_state(w, "", "(on entry)")?;
-        self.prev_state.overwrite(self.results.get());
+        self.write_row_with_full_state(w, "", "(on_entry)")?;
 
         // D: Statement transfer functions
         for (i, statement) in body[block].statements.iter().enumerate() {
             let location = Location { block, statement_index: i };
-
-            let mir_col = format!("{:?}", statement);
-            let i_col = i.to_string();
-
-            self.results.seek_after(location);
-            self.write_row_with_curr_diff(w, &i_col, &mir_col)?;
-            self.prev_state.overwrite(self.results.get());
+            let statement_str = format!("{:?}", statement);
+            self.write_row_for_location(w, &i.to_string(), &statement_str, location)?;
         }
 
         // E: Terminator transfer function
         let terminator = body[block].terminator();
-        let location = body.terminator_loc(block);
+        let terminator_loc = body.terminator_loc(block);
+        let mut terminator_str = String::new();
+        terminator.kind.fmt_head(&mut terminator_str).unwrap();
 
-        let mut mir_col = String::new();
-        terminator.kind.fmt_head(&mut mir_col).unwrap();
-
-        self.results.seek_after(location);
-        self.write_row_with_curr_diff(w, "T", &mir_col)?;
-        self.prev_state.overwrite(self.results.get());
+        self.write_row_for_location(w, "T", &terminator_str, terminator_loc)?;
 
         // F: Exit state
+        self.results.seek_after(terminator_loc);
         if let mir::TerminatorKind::Call { destination: Some(_), .. } = &terminator.kind {
-            self.write_row_with_curr_state(w, "", "(on unwind)")?;
+            self.write_row_with_full_state(w, "", "(on unwind)")?;
 
-            self.results.seek_after_assume_call_returns(location);
-            self.write_row_with_curr_diff(w, "", "(on successful return)")?;
+            let num_state_columns = self.num_state_columns();
+            self.write_row(w, "", "(on successful return)", |this, w, fmt| {
+                write!(
+                    w,
+                    r#"<td colspan="{colspan}" {fmt} align="left">"#,
+                    colspan = num_state_columns,
+                    fmt = fmt,
+                )?;
+
+                let state_on_unwind = this.results.get().clone();
+                this.results.seek_after_assume_call_returns(terminator_loc);
+                write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?;
+
+                write!(w, "</td>")
+            })?;
         } else {
-            self.write_row_with_curr_state(w, "", "(on exit)")?;
+            self.write_row_with_full_state(w, "", "(on exit)")?;
         }
 
         write!(w, "</table>")
     }
 
-    fn write_row_with_curr_state(
+    fn write_block_header_simple(
         &mut self,
         w: &mut impl io::Write,
-        i: &str,
-        mir: &str,
+        block: BasicBlock,
     ) -> io::Result<()> {
-        let bg = self.toggle_background();
+        //   +-------------------------------------------------+
+        // A |                      bb4                        |
+        //   +-----------------------------------+-------------+
+        // B |                MIR                |    STATE    |
+        //   +-+---------------------------------+-------------+
+        //   | |              ...                |             |
 
-        let mut out = Vec::new();
-        write!(&mut out, "{{")?;
-        pretty_print_state_elems(&mut out, self.results.analysis(), self.results.get().iter())?;
-        write!(&mut out, "}}")?;
-
+        // A
         write!(
             w,
-            r#"<tr>
-                 <td {fmt} align="right">{i}</td>
-                 <td {fmt} align="left">{mir}</td>
-                 <td {fmt} align="left">{state}</td>
-               </tr>"#,
-            fmt = &["sides=\"tl\"", bg.attr()].join(" "),
-            i = i,
-            mir = dot::escape_html(mir),
-            state = dot::escape_html(str::from_utf8(&out).unwrap()),
+            concat!("<tr>", r#"<td colspan="3" sides="tl">bb{block_id}</td>"#, "</tr>",),
+            block_id = block.index(),
+        )?;
+
+        // B
+        write!(
+            w,
+            concat!(
+                "<tr>",
+                r#"<td colspan="2" {fmt}>MIR</td>"#,
+                r#"<td {fmt}>STATE</td>"#,
+                "</tr>",
+            ),
+            fmt = format!("bgcolor=\"{}\" sides=\"tl\"", Self::HEADER_COLOR),
         )
     }
 
-    fn write_row_with_curr_diff(
+    fn write_block_header_with_state_columns(
+        &mut self,
+        w: &mut impl io::Write,
+        block: BasicBlock,
+    ) -> io::Result<()> {
+        //   +------------------------------------+-------------+
+        // A |                bb4                 |    STATE    |
+        //   +------------------------------------+------+------+
+        // B |                MIR                 |  GEN | KILL |
+        //   +-+----------------------------------+------+------+
+        //   | |              ...                 |      |      |
+
+        let state_column_names = self.state_formatter.column_names();
+
+        // A
+        write!(
+            w,
+            concat!(
+                "<tr>",
+                r#"<td {fmt} colspan="2">bb{block_id}</td>"#,
+                r#"<td {fmt} colspan="{num_state_cols}">STATE</td>"#,
+                "</tr>",
+            ),
+            fmt = "sides=\"tl\"",
+            num_state_cols = state_column_names.len(),
+            block_id = block.index(),
+        )?;
+
+        // B
+        let fmt = format!("bgcolor=\"{}\" sides=\"tl\"", Self::HEADER_COLOR);
+        write!(w, concat!("<tr>", r#"<td colspan="2" {fmt}>MIR</td>"#,), fmt = fmt,)?;
+
+        for name in state_column_names {
+            write!(w, "<td {fmt}>{name}</td>", fmt = fmt, name = name)?;
+        }
+
+        write!(w, "</tr>")
+    }
+
+    /// Write a row with the given index and MIR, using the function argument to fill in the
+    /// "STATE" column(s).
+    fn write_row<W: io::Write>(
+        &mut self,
+        w: &mut W,
+        i: &str,
+        mir: &str,
+        f: impl FnOnce(&mut Self, &mut W, &str) -> io::Result<()>,
+    ) -> io::Result<()> {
+        let bg = self.toggle_background();
+        let fmt = format!("sides=\"tl\" {}", bg.attr());
+
+        write!(
+            w,
+            concat!(
+                "<tr>",
+                r#"<td {fmt} align="right">{i}</td>"#,
+                r#"<td {fmt} align="left">{mir}</td>"#,
+            ),
+            i = i,
+            fmt = fmt,
+            mir = dot::escape_html(mir),
+        )?;
+
+        f(self, w, &fmt)?;
+        write!(w, "</tr>")
+    }
+
+    fn write_row_with_full_state(
         &mut self,
         w: &mut impl io::Write,
         i: &str,
         mir: &str,
     ) -> io::Result<()> {
-        let bg = self.toggle_background();
-        let analysis = self.results.analysis();
+        self.write_row(w, i, mir, |this, w, fmt| {
+            let state = this.results.get();
+            let analysis = this.results.analysis();
 
-        let diff = BitSetDiff::compute(&self.prev_state, self.results.get());
-
-        let mut set = Vec::new();
-        pretty_print_state_elems(&mut set, analysis, diff.set.iter())?;
-
-        let mut clear = Vec::new();
-        pretty_print_state_elems(&mut clear, analysis, diff.clear.iter())?;
-
-        write!(
-            w,
-            r#"<tr>
-                 <td {fmt} align="right">{i}</td>
-                 <td {fmt} align="left">{mir}</td>
-                 <td {fmt} align="left">"#,
-            i = i,
-            fmt = &["sides=\"tl\"", bg.attr()].join(" "),
-            mir = dot::escape_html(mir),
-        )?;
-
-        if !set.is_empty() {
             write!(
                 w,
-                r#"<font color="darkgreen">+{}</font>"#,
-                dot::escape_html(str::from_utf8(&set).unwrap()),
+                r#"<td colspan="{colspan}" {fmt} align="left">{{"#,
+                colspan = this.num_state_columns(),
+                fmt = fmt,
             )?;
-        }
+            pretty_print_state_elems(w, analysis, state.iter(), ",", LIMIT_40_ALIGN_1)?;
+            write!(w, "}}</td>")
+        })
+    }
 
-        if !set.is_empty() && !clear.is_empty() {
-            write!(w, "  ")?;
-        }
-
-        if !clear.is_empty() {
-            write!(
-                w,
-                r#"<font color="red">-{}</font>"#,
-                dot::escape_html(str::from_utf8(&clear).unwrap()),
-            )?;
-        }
-
-        write!(w, "</td></tr>")
+    fn write_row_for_location(
+        &mut self,
+        w: &mut impl io::Write,
+        i: &str,
+        mir: &str,
+        location: Location,
+    ) -> io::Result<()> {
+        self.write_row(w, i, mir, |this, w, fmt| {
+            this.state_formatter.write_state_for_location(w, fmt, &mut this.results, location)
+        })
     }
 }
 
-/// The operations required to transform one `BitSet` into another.
-struct BitSetDiff<T: Idx> {
-    set: HybridBitSet<T>,
-    clear: HybridBitSet<T>,
+/// Controls what gets printed under the `STATE` header.
+pub trait StateFormatter<'tcx, A>
+where
+    A: Analysis<'tcx>,
+{
+    /// The columns that will get printed under `STATE`.
+    fn column_names(&self) -> &[&str];
+
+    fn write_state_for_location(
+        &mut self,
+        w: &mut dyn io::Write,
+        fmt: &str,
+        results: &mut ResultsRefCursor<'_, '_, 'tcx, A>,
+        location: Location,
+    ) -> io::Result<()>;
 }
 
-impl<T: Idx> BitSetDiff<T> {
-    fn compute(from: &BitSet<T>, to: &BitSet<T>) -> Self {
-        assert_eq!(from.domain_size(), to.domain_size());
-        let len = from.domain_size();
+/// Prints a single column containing the state vector immediately *after* each statement.
+pub struct SimpleDiff<T: Idx> {
+    prev_state: BitSet<T>,
+    prev_loc: Location,
+}
 
-        let mut set = HybridBitSet::new_empty(len);
-        let mut clear = HybridBitSet::new_empty(len);
-
-        // FIXME: This could be made faster if `BitSet::xor` were implemented.
-        for i in (0..len).map(|i| T::new(i)) {
-            match (from.contains(i), to.contains(i)) {
-                (false, true) => set.insert(i),
-                (true, false) => clear.insert(i),
-                _ => continue,
-            };
-        }
-
-        BitSetDiff { set, clear }
+impl<T: Idx> SimpleDiff<T> {
+    #![allow(unused)]
+    pub fn new(bits_per_block: usize) -> Self {
+        SimpleDiff { prev_state: BitSet::new_empty(bits_per_block), prev_loc: Location::START }
     }
 }
 
-/// Formats each `elem` using the pretty printer provided by `analysis` into a comma-separated
-/// list.
+impl<A> StateFormatter<'tcx, A> for SimpleDiff<A::Idx>
+where
+    A: Analysis<'tcx>,
+{
+    fn column_names(&self) -> &[&str] {
+        &[]
+    }
+
+    fn write_state_for_location(
+        &mut self,
+        mut w: &mut dyn io::Write,
+        fmt: &str,
+        results: &mut ResultsRefCursor<'_, '_, 'tcx, A>,
+        location: Location,
+    ) -> io::Result<()> {
+        if location.statement_index == 0 {
+            results.seek_to_block_start(location.block);
+            self.prev_state.overwrite(results.get());
+        } else {
+            // Ensure that we are visiting statements in order, so `prev_state` is correct.
+            assert_eq!(self.prev_loc.successor_within_block(), location);
+        }
+
+        self.prev_loc = location;
+        write!(w, r#"<td {fmt} align="left">"#, fmt = fmt)?;
+        results.seek_before(location);
+        let curr_state = results.get();
+        write_diff(&mut w, results.analysis(), &self.prev_state, curr_state)?;
+        self.prev_state.overwrite(curr_state);
+        write!(w, "</td>")
+    }
+}
+
+/// Prints two state columns, one containing only the "before" effect of each statement and one
+/// containing the full effect.
+pub struct TwoPhaseDiff<T: Idx> {
+    prev_state: BitSet<T>,
+    prev_loc: Location,
+}
+
+impl<T: Idx> TwoPhaseDiff<T> {
+    #![allow(unused)]
+    pub fn new(bits_per_block: usize) -> Self {
+        TwoPhaseDiff { prev_state: BitSet::new_empty(bits_per_block), prev_loc: Location::START }
+    }
+}
+
+impl<A> StateFormatter<'tcx, A> for TwoPhaseDiff<A::Idx>
+where
+    A: Analysis<'tcx>,
+{
+    fn column_names(&self) -> &[&str] {
+        &["ENTRY", " EXIT"]
+    }
+
+    fn write_state_for_location(
+        &mut self,
+        mut w: &mut dyn io::Write,
+        fmt: &str,
+        results: &mut ResultsRefCursor<'_, '_, 'tcx, A>,
+        location: Location,
+    ) -> io::Result<()> {
+        if location.statement_index == 0 {
+            results.seek_to_block_start(location.block);
+            self.prev_state.overwrite(results.get());
+        } else {
+            // Ensure that we are visiting statements in order, so `prev_state` is correct.
+            assert_eq!(self.prev_loc.successor_within_block(), location);
+        }
+
+        self.prev_loc = location;
+
+        // Entry
+
+        write!(w, r#"<td {fmt} align="left">"#, fmt = fmt)?;
+        results.seek_before(location);
+        let curr_state = results.get();
+        write_diff(&mut w, results.analysis(), &self.prev_state, curr_state)?;
+        self.prev_state.overwrite(curr_state);
+        write!(w, "</td>")?;
+
+        // Exit
+
+        write!(w, r#"<td {fmt} align="left">"#, fmt = fmt)?;
+        results.seek_after(location);
+        let curr_state = results.get();
+        write_diff(&mut w, results.analysis(), &self.prev_state, curr_state)?;
+        self.prev_state.overwrite(curr_state);
+        write!(w, "</td>")
+    }
+}
+
+/// Prints the gen/kill set for the entire block.
+pub struct BlockTransferFunc<'a, 'tcx, T: Idx> {
+    body: &'a mir::Body<'tcx>,
+    trans_for_block: IndexVec<BasicBlock, GenKillSet<T>>,
+}
+
+impl<T: Idx> BlockTransferFunc<'mir, 'tcx, T> {
+    #![allow(unused)]
+    pub fn new(
+        body: &'mir mir::Body<'tcx>,
+        trans_for_block: IndexVec<BasicBlock, GenKillSet<T>>,
+    ) -> Self {
+        BlockTransferFunc { body, trans_for_block }
+    }
+}
+
+impl<A> StateFormatter<'tcx, A> for BlockTransferFunc<'mir, 'tcx, A::Idx>
+where
+    A: Analysis<'tcx>,
+{
+    fn column_names(&self) -> &[&str] {
+        &["GEN", "KILL"]
+    }
+
+    fn write_state_for_location(
+        &mut self,
+        mut w: &mut dyn io::Write,
+        fmt: &str,
+        results: &mut ResultsRefCursor<'_, '_, 'tcx, A>,
+        location: Location,
+    ) -> io::Result<()> {
+        // Only print a single row.
+        if location.statement_index != 0 {
+            return Ok(());
+        }
+
+        let block_trans = &self.trans_for_block[location.block];
+        let rowspan = self.body.basic_blocks()[location.block].statements.len();
+
+        for set in &[&block_trans.gen, &block_trans.kill] {
+            write!(
+                w,
+                r#"<td {fmt} rowspan="{rowspan}" align="center">"#,
+                fmt = fmt,
+                rowspan = rowspan
+            )?;
+
+            pretty_print_state_elems(&mut w, results.analysis(), set.iter(), "\n", None)?;
+            write!(w, "</td>")?;
+        }
+
+        Ok(())
+    }
+}
+
+/// Writes two lines, one containing the added bits and one the removed bits.
+fn write_diff<A: Analysis<'tcx>>(
+    w: &mut impl io::Write,
+    analysis: &A,
+    from: &BitSet<A::Idx>,
+    to: &BitSet<A::Idx>,
+) -> io::Result<()> {
+    assert_eq!(from.domain_size(), to.domain_size());
+    let len = from.domain_size();
+
+    let mut set = HybridBitSet::new_empty(len);
+    let mut clear = HybridBitSet::new_empty(len);
+
+    // FIXME: Implement a lazy iterator over the symmetric difference of two bitsets.
+    for i in (0..len).map(|i| A::Idx::new(i)) {
+        match (from.contains(i), to.contains(i)) {
+            (false, true) => set.insert(i),
+            (true, false) => clear.insert(i),
+            _ => continue,
+        };
+    }
+
+    if !set.is_empty() {
+        write!(w, r#"<font color="darkgreen">+"#)?;
+        pretty_print_state_elems(w, analysis, set.iter(), ",", LIMIT_40_ALIGN_1)?;
+        write!(w, r#"</font>"#)?;
+    }
+
+    if !set.is_empty() && !clear.is_empty() {
+        write!(w, "<br/>")?;
+    }
+
+    if !clear.is_empty() {
+        write!(w, r#"<font color="red">-"#)?;
+        pretty_print_state_elems(w, analysis, clear.iter(), ",", LIMIT_40_ALIGN_1)?;
+        write!(w, r#"</font>"#)?;
+    }
+
+    Ok(())
+}
+
+/// Line break policy that breaks at 40 characters and starts the next line with a single space.
+const LIMIT_40_ALIGN_1: Option<LineBreak> = Some(LineBreak { sequence: "<br/> ", limit: 40 });
+
+struct LineBreak {
+    sequence: &'static str,
+    limit: usize,
+}
+
+/// Formats each `elem` using the pretty printer provided by `analysis` into a list with the given
+/// separator (`sep`).
+///
+/// Optionally, it will break lines using the given character sequence (usually `<br/>`) and
+/// character limit.
 fn pretty_print_state_elems<A>(
     w: &mut impl io::Write,
     analysis: &A,
     elems: impl Iterator<Item = A::Idx>,
-) -> io::Result<()>
+    sep: &str,
+    line_break: Option<LineBreak>,
+) -> io::Result<bool>
 where
     A: Analysis<'tcx>,
 {
+    let sep_width = sep.chars().count();
+
+    let mut buf = Vec::new();
+
     let mut first = true;
+    let mut curr_line_width = 0;
+    let mut line_break_inserted = false;
+
     for idx in elems {
         if first {
             first = false;
         } else {
-            write!(w, ",")?;
+            write!(w, "{}", sep)?;
+            curr_line_width += sep_width;
         }
 
-        analysis.pretty_print_idx(w, idx)?;
+        buf.clear();
+        analysis.pretty_print_idx(&mut buf, idx)?;
+        let idx_str =
+            str::from_utf8(&buf).expect("Output of `pretty_print_idx` must be valid UTF-8");
+        let escaped = dot::escape_html(idx_str);
+        let escaped_width = escaped.chars().count();
+
+        if let Some(line_break) = &line_break {
+            if curr_line_width + sep_width + escaped_width > line_break.limit {
+                write!(w, "{}", line_break.sequence)?;
+                line_break_inserted = true;
+                curr_line_width = 0;
+            }
+        }
+
+        write!(w, "{}", escaped)?;
+        curr_line_width += escaped_width;
     }
 
-    Ok(())
+    Ok(line_break_inserted)
 }
 
 /// The background color used for zebra-striping the table.
diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs
new file mode 100644
index 0000000..c9b4f87
--- /dev/null
+++ b/src/librustc_mir/dataflow/generic/mod.rs
@@ -0,0 +1,358 @@
+//! A framework that can express both [gen-kill] and generic dataflow problems.
+//!
+//! There is another interface for dataflow in the compiler in `librustc_mir/dataflow/mod.rs`. The
+//! interface in this module will eventually [replace that one][design-meeting].
+//!
+//! To actually use this framework, you must implement either the `Analysis` or the `GenKillAnalysis`
+//! trait. If your transfer function can be expressed with only gen/kill operations, prefer
+//! `GenKillAnalysis` since it will run faster while iterating to fixpoint. Create an `Engine` using
+//! the appropriate constructor and call `iterate_to_fixpoint`. You can use a `ResultsCursor` to
+//! inspect the fixpoint solution to your dataflow problem.
+//!
+//! ```ignore(cross-crate-imports)
+//! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, did: DefId) {
+//!     let analysis = MyAnalysis::new();
+//!
+//!     // If `MyAnalysis` implements `GenKillAnalysis`.
+//!     let results = Engine::new_gen_kill(tcx, body, did, analysis).iterate_to_fixpoint();
+//!
+//!     // If `MyAnalysis` implements `Analysis`.
+//!     // let results = Engine::new_generic(tcx, body, did, analysis).iterate_to_fixpoint();
+//!
+//!     let mut cursor = ResultsCursor::new(body, results);
+//!
+//!     for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() {
+//!         cursor.seek_after(Location { block: START_BLOCK, statement_index });
+//!         let state = cursor.get();
+//!         println!("{:?}", state);
+//!     }
+//! }
+//! ```
+//!
+//! [gen-kill]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
+//! [design-meeting]https://github.com/rust-lang/compiler-team/issues/202
+
+use std::io;
+
+use rustc::mir::{self, BasicBlock, Location};
+use rustc_index::bit_set::{BitSet, HybridBitSet};
+use rustc_index::vec::{Idx, IndexVec};
+
+use crate::dataflow::BottomValue;
+
+mod cursor;
+mod engine;
+mod graphviz;
+
+pub use self::cursor::{ResultsCursor, ResultsRefCursor};
+pub use self::engine::Engine;
+
+/// A dataflow analysis that has converged to fixpoint.
+pub struct Results<'tcx, A>
+where
+    A: Analysis<'tcx>,
+{
+    pub analysis: A,
+    entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
+}
+
+impl<A> Results<'tcx, A>
+where
+    A: Analysis<'tcx>,
+{
+    /// Creates a `ResultsCursor` that can inspect these `Results`.
+    pub fn into_results_cursor(self, body: &'mir mir::Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> {
+        ResultsCursor::new(body, self)
+    }
+
+    /// Gets the entry set for the given block.
+    pub fn entry_set_for_block(&self, block: BasicBlock) -> &BitSet<A::Idx> {
+        &self.entry_sets[block]
+    }
+}
+
+/// Define the domain of a dataflow problem.
+///
+/// This trait specifies the lattice on which this analysis operates. For now, this must be a
+/// powerset of values of type `Idx`. The elements of this lattice are represented with a `BitSet`
+/// and referred to as the state vector.
+///
+/// This trait also defines the initial value for the dataflow state upon entry to the
+/// `START_BLOCK`, as well as some names used to refer to this analysis when debugging.
+pub trait AnalysisDomain<'tcx>: BottomValue {
+    /// The type of the elements in the state vector.
+    type Idx: Idx;
+
+    /// A descriptive name for this analysis. Used only for debugging.
+    ///
+    /// This name should be brief and contain no spaces, periods or other characters that are not
+    /// suitable as part of a filename.
+    const NAME: &'static str;
+
+    /// The size of the state vector.
+    fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize;
+
+    /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow
+    /// analysis.
+    fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>);
+
+    /// Prints an element in the state vector for debugging.
+    fn pretty_print_idx(&self, w: &mut impl io::Write, idx: Self::Idx) -> io::Result<()> {
+        write!(w, "{:?}", idx)
+    }
+}
+
+/// A dataflow problem with an arbitrarily complex transfer function.
+pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
+    /// Updates the current dataflow state with the effect of evaluating a statement.
+    fn apply_statement_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        statement: &mir::Statement<'tcx>,
+        location: Location,
+    );
+
+    /// Updates the current dataflow state with an effect that occurs immediately *before* the
+    /// given statement.
+    ///
+    /// This method is useful if the consumer of the results of this analysis needs only to observe
+    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
+    /// analyses should not implement this without implementing `apply_statement_effect`.
+    fn apply_before_statement_effect(
+        &self,
+        _state: &mut BitSet<Self::Idx>,
+        _statement: &mir::Statement<'tcx>,
+        _location: Location,
+    ) {
+    }
+
+    /// Updates the current dataflow state with the effect of evaluating a terminator.
+    ///
+    /// The effect of a successful return from a `Call` terminator should **not** be accounted for
+    /// in this function. That should go in `apply_call_return_effect`. For example, in the
+    /// `InitializedPlaces` analyses, the return place for a function call is not marked as
+    /// initialized here.
+    fn apply_terminator_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        terminator: &mir::Terminator<'tcx>,
+        location: Location,
+    );
+
+    /// Updates the current dataflow state with an effect that occurs immediately *before* the
+    /// given terminator.
+    ///
+    /// This method is useful if the consumer of the results of this analysis needs only to observe
+    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
+    /// analyses should not implement this without implementing `apply_terminator_effect`.
+    fn apply_before_terminator_effect(
+        &self,
+        _state: &mut BitSet<Self::Idx>,
+        _terminator: &mir::Terminator<'tcx>,
+        _location: Location,
+    ) {
+    }
+
+    /// Updates the current dataflow state with the effect of a successful return from a `Call`
+    /// terminator.
+    ///
+    /// This is separate from `apply_terminator_effect` to properly track state across unwind
+    /// edges.
+    fn apply_call_return_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        block: BasicBlock,
+        func: &mir::Operand<'tcx>,
+        args: &[mir::Operand<'tcx>],
+        return_place: &mir::Place<'tcx>,
+    );
+}
+
+/// A gen/kill dataflow problem.
+///
+/// Each method in this trait has a corresponding one in `Analysis`. However, these methods only
+/// allow modification of the dataflow state via "gen" and "kill" operations. By defining transfer
+/// functions for each statement in this way, the transfer function for an entire basic block can
+/// be computed efficiently.
+///
+/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`.
+pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
+    /// See `Analysis::apply_statement_effect`.
+    fn statement_effect(
+        &self,
+        trans: &mut impl GenKill<Self::Idx>,
+        statement: &mir::Statement<'tcx>,
+        location: Location,
+    );
+
+    /// See `Analysis::apply_before_statement_effect`.
+    fn before_statement_effect(
+        &self,
+        _trans: &mut impl GenKill<Self::Idx>,
+        _statement: &mir::Statement<'tcx>,
+        _location: Location,
+    ) {
+    }
+
+    /// See `Analysis::apply_terminator_effect`.
+    fn terminator_effect(
+        &self,
+        trans: &mut impl GenKill<Self::Idx>,
+        terminator: &mir::Terminator<'tcx>,
+        location: Location,
+    );
+
+    /// See `Analysis::apply_before_terminator_effect`.
+    fn before_terminator_effect(
+        &self,
+        _trans: &mut impl GenKill<Self::Idx>,
+        _terminator: &mir::Terminator<'tcx>,
+        _location: Location,
+    ) {
+    }
+
+    /// See `Analysis::apply_call_return_effect`.
+    fn call_return_effect(
+        &self,
+        trans: &mut impl GenKill<Self::Idx>,
+        block: BasicBlock,
+        func: &mir::Operand<'tcx>,
+        args: &[mir::Operand<'tcx>],
+        return_place: &mir::Place<'tcx>,
+    );
+}
+
+impl<A> Analysis<'tcx> for A
+where
+    A: GenKillAnalysis<'tcx>,
+{
+    fn apply_statement_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        self.statement_effect(state, statement, location);
+    }
+
+    fn apply_before_statement_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        self.before_statement_effect(state, statement, location);
+    }
+
+    fn apply_terminator_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        terminator: &mir::Terminator<'tcx>,
+        location: Location,
+    ) {
+        self.terminator_effect(state, terminator, location);
+    }
+
+    fn apply_before_terminator_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        terminator: &mir::Terminator<'tcx>,
+        location: Location,
+    ) {
+        self.before_terminator_effect(state, terminator, location);
+    }
+
+    fn apply_call_return_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        block: BasicBlock,
+        func: &mir::Operand<'tcx>,
+        args: &[mir::Operand<'tcx>],
+        return_place: &mir::Place<'tcx>,
+    ) {
+        self.call_return_effect(state, block, func, args, return_place);
+    }
+}
+
+/// The legal operations for a transfer function in a gen/kill problem.
+///
+/// This abstraction exists because there are two different contexts in which we call the methods in
+/// `GenKillAnalysis`. Sometimes we need to store a single transfer function that can be efficiently
+/// applied multiple times, such as when computing the cumulative transfer function for each block.
+/// These cases require a `GenKillSet`, which in turn requires two `BitSet`s of storage. Oftentimes,
+/// however, we only need to apply an effect once. In *these* cases, it is more efficient to pass the
+/// `BitSet` representing the state vector directly into the `*_effect` methods as opposed to
+/// building up a `GenKillSet` and then throwing it away.
+pub trait GenKill<T> {
+    /// Inserts `elem` into the state vector.
+    fn gen(&mut self, elem: T);
+
+    /// Removes `elem` from the state vector.
+    fn kill(&mut self, elem: T);
+
+    /// Calls `gen` for each element in `elems`.
+    fn gen_all(&mut self, elems: impl IntoIterator<Item = T>) {
+        for elem in elems {
+            self.gen(elem);
+        }
+    }
+
+    /// Calls `kill` for each element in `elems`.
+    fn kill_all(&mut self, elems: impl IntoIterator<Item = T>) {
+        for elem in elems {
+            self.kill(elem);
+        }
+    }
+}
+
+/// Stores a transfer function for a gen/kill problem.
+///
+/// Calling `gen`/`kill` on a `GenKillSet` will "build up" a transfer function so that it can be
+/// applied multiple times efficiently. When there are multiple calls to `gen` and/or `kill` for
+/// the same element, the most recent one takes precedence.
+#[derive(Clone)]
+pub struct GenKillSet<T: Idx> {
+    gen: HybridBitSet<T>,
+    kill: HybridBitSet<T>,
+}
+
+impl<T: Idx> GenKillSet<T> {
+    /// Creates a new transfer function that will leave the dataflow state unchanged.
+    pub fn identity(universe: usize) -> Self {
+        GenKillSet {
+            gen: HybridBitSet::new_empty(universe),
+            kill: HybridBitSet::new_empty(universe),
+        }
+    }
+
+    /// Applies this transfer function to the given state vector.
+    pub fn apply(&self, state: &mut BitSet<T>) {
+        state.union(&self.gen);
+        state.subtract(&self.kill);
+    }
+}
+
+impl<T: Idx> GenKill<T> for GenKillSet<T> {
+    fn gen(&mut self, elem: T) {
+        self.gen.insert(elem);
+        self.kill.remove(elem);
+    }
+
+    fn kill(&mut self, elem: T) {
+        self.kill.insert(elem);
+        self.gen.remove(elem);
+    }
+}
+
+impl<T: Idx> GenKill<T> for BitSet<T> {
+    fn gen(&mut self, elem: T) {
+        self.insert(elem);
+    }
+
+    fn kill(&mut self, elem: T) {
+        self.remove(elem);
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustc_mir/dataflow/generic/tests.rs b/src/librustc_mir/dataflow/generic/tests.rs
new file mode 100644
index 0000000..50d4bdb
--- /dev/null
+++ b/src/librustc_mir/dataflow/generic/tests.rs
@@ -0,0 +1,332 @@
+//! A test for the logic that updates the state in a `ResultsCursor` during seek.
+
+use rustc::mir::{self, BasicBlock, Location};
+use rustc::ty;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::IndexVec;
+use rustc_span::DUMMY_SP;
+
+use super::*;
+use crate::dataflow::BottomValue;
+
+/// Returns `true` if the given location points to a `Call` terminator that can return
+/// successfully.
+fn is_call_terminator_non_diverging(body: &mir::Body<'_>, loc: Location) -> bool {
+    loc == body.terminator_loc(loc.block)
+        && matches!(
+            body[loc.block].terminator().kind,
+            mir::TerminatorKind::Call { destination: Some(_), ..  }
+        )
+}
+
+/// Creates a `mir::Body` with a few disconnected basic blocks.
+///
+/// This is the `Body` that will be used by the `MockAnalysis` below. The shape of its CFG is not
+/// important.
+fn mock_body() -> mir::Body<'static> {
+    let source_info = mir::SourceInfo { scope: mir::OUTERMOST_SOURCE_SCOPE, span: DUMMY_SP };
+
+    let mut blocks = IndexVec::new();
+    let mut block = |n, kind| {
+        let nop = mir::Statement { source_info, kind: mir::StatementKind::Nop };
+
+        blocks.push(mir::BasicBlockData {
+            statements: std::iter::repeat(&nop).cloned().take(n).collect(),
+            terminator: Some(mir::Terminator { source_info, kind }),
+            is_cleanup: false,
+        })
+    };
+
+    let dummy_place = mir::Place { local: mir::RETURN_PLACE, projection: ty::List::empty() };
+
+    block(4, mir::TerminatorKind::Return);
+    block(1, mir::TerminatorKind::Return);
+    block(
+        2,
+        mir::TerminatorKind::Call {
+            func: mir::Operand::Copy(dummy_place.clone()),
+            args: vec![],
+            destination: Some((dummy_place.clone(), mir::START_BLOCK)),
+            cleanup: None,
+            from_hir_call: false,
+        },
+    );
+    block(3, mir::TerminatorKind::Return);
+    block(0, mir::TerminatorKind::Return);
+    block(
+        4,
+        mir::TerminatorKind::Call {
+            func: mir::Operand::Copy(dummy_place.clone()),
+            args: vec![],
+            destination: Some((dummy_place.clone(), mir::START_BLOCK)),
+            cleanup: None,
+            from_hir_call: false,
+        },
+    );
+
+    mir::Body::new_cfg_only(blocks)
+}
+
+/// A dataflow analysis whose state is unique at every possible `SeekTarget`.
+///
+/// Uniqueness is achieved by having a *locally* unique effect before and after each statement and
+/// terminator (see `effect_at_target`) while ensuring that the entry set for each block is
+/// *globally* unique (see `mock_entry_set`).
+///
+/// For example, a `BasicBlock` with ID `2` and a `Call` terminator has the following state at each
+/// location ("+x" indicates that "x" is added to the state).
+///
+/// | Location               | Before            | After  |
+/// |------------------------|-------------------|--------|
+/// | (on_entry)             | {102}                     ||
+/// | Statement 0            | +0                | +1     |
+/// | statement 1            | +2                | +3     |
+/// | `Call` terminator      | +4                | +5     |
+/// | (on unwind)            | {102,0,1,2,3,4,5}         ||
+/// | (on successful return) | +6                        ||
+///
+/// The `102` in the block's entry set is derived from the basic block index and ensures that the
+/// expected state is unique across all basic blocks. Remember, it is generated by
+/// `mock_entry_sets`, not from actually running `MockAnalysis` to fixpoint.
+struct MockAnalysis<'tcx> {
+    body: &'tcx mir::Body<'tcx>,
+}
+
+impl MockAnalysis<'tcx> {
+    const BASIC_BLOCK_OFFSET: usize = 100;
+
+    /// The entry set for each `BasicBlock` is the ID of that block offset by a fixed amount to
+    /// avoid colliding with the statement/terminator effects.
+    fn mock_entry_set(&self, bb: BasicBlock) -> BitSet<usize> {
+        let mut ret = BitSet::new_empty(self.bits_per_block(self.body));
+        ret.insert(Self::BASIC_BLOCK_OFFSET + bb.index());
+        ret
+    }
+
+    fn mock_entry_sets(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
+        let empty = BitSet::new_empty(self.bits_per_block(self.body));
+        let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks());
+
+        for (bb, _) in self.body.basic_blocks().iter_enumerated() {
+            ret[bb] = self.mock_entry_set(bb);
+        }
+
+        ret
+    }
+
+    /// Returns the index that should be added to the dataflow state at the given target.
+    ///
+    /// This index is only unique within a given basic block. `SeekAfter` and
+    /// `SeekAfterAssumeCallReturns` have the same effect unless `target` is a `Call` terminator.
+    fn effect_at_target(&self, target: SeekTarget) -> Option<usize> {
+        use SeekTarget::*;
+
+        let idx = match target {
+            BlockStart(_) => return None,
+
+            AfterAssumeCallReturns(loc) if is_call_terminator_non_diverging(self.body, loc) => {
+                loc.statement_index * 2 + 2
+            }
+
+            Before(loc) => loc.statement_index * 2,
+            After(loc) | AfterAssumeCallReturns(loc) => loc.statement_index * 2 + 1,
+        };
+
+        assert!(idx < Self::BASIC_BLOCK_OFFSET, "Too many statements in basic block");
+        Some(idx)
+    }
+
+    /// Returns the expected state at the given `SeekTarget`.
+    ///
+    /// This is the union of index of the target basic block, the index assigned to the
+    /// target statement or terminator, and the indices of all preceding statements in the target
+    /// basic block.
+    ///
+    /// For example, the expected state when calling
+    /// `seek_before(Location { block: 2, statement_index: 2 })` would be `[102, 0, 1, 2, 3, 4]`.
+    fn expected_state_at_target(&self, target: SeekTarget) -> BitSet<usize> {
+        let mut ret = BitSet::new_empty(self.bits_per_block(self.body));
+        ret.insert(Self::BASIC_BLOCK_OFFSET + target.block().index());
+
+        if let Some(target_effect) = self.effect_at_target(target) {
+            for i in 0..=target_effect {
+                ret.insert(i);
+            }
+        }
+
+        ret
+    }
+}
+
+impl BottomValue for MockAnalysis<'tcx> {
+    const BOTTOM_VALUE: bool = false;
+}
+
+impl AnalysisDomain<'tcx> for MockAnalysis<'tcx> {
+    type Idx = usize;
+
+    const NAME: &'static str = "mock";
+
+    fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize {
+        Self::BASIC_BLOCK_OFFSET + body.basic_blocks().len()
+    }
+
+    fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut BitSet<Self::Idx>) {
+        unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint");
+    }
+}
+
+impl Analysis<'tcx> for MockAnalysis<'tcx> {
+    fn apply_statement_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        _statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        let idx = self.effect_at_target(SeekTarget::After(location)).unwrap();
+        assert!(state.insert(idx));
+    }
+
+    fn apply_before_statement_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        _statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        let idx = self.effect_at_target(SeekTarget::Before(location)).unwrap();
+        assert!(state.insert(idx));
+    }
+
+    fn apply_terminator_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        _terminator: &mir::Terminator<'tcx>,
+        location: Location,
+    ) {
+        let idx = self.effect_at_target(SeekTarget::After(location)).unwrap();
+        assert!(state.insert(idx));
+    }
+
+    fn apply_before_terminator_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        _terminator: &mir::Terminator<'tcx>,
+        location: Location,
+    ) {
+        let idx = self.effect_at_target(SeekTarget::Before(location)).unwrap();
+        assert!(state.insert(idx));
+    }
+
+    fn apply_call_return_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        block: BasicBlock,
+        _func: &mir::Operand<'tcx>,
+        _args: &[mir::Operand<'tcx>],
+        _return_place: &mir::Place<'tcx>,
+    ) {
+        let location = self.body.terminator_loc(block);
+        let idx = self.effect_at_target(SeekTarget::AfterAssumeCallReturns(location)).unwrap();
+        assert!(state.insert(idx));
+    }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum SeekTarget {
+    BlockStart(BasicBlock),
+    Before(Location),
+    After(Location),
+    AfterAssumeCallReturns(Location),
+}
+
+impl SeekTarget {
+    fn block(&self) -> BasicBlock {
+        use SeekTarget::*;
+
+        match *self {
+            BlockStart(block) => block,
+            Before(loc) | After(loc) | AfterAssumeCallReturns(loc) => loc.block,
+        }
+    }
+
+    /// An iterator over all possible `SeekTarget`s in a given block in order, starting with
+    /// `BlockStart`.
+    ///
+    /// This includes both `After` and `AfterAssumeCallReturns` for every `Location`.
+    fn iter_in_block(body: &mir::Body<'_>, block: BasicBlock) -> impl Iterator<Item = Self> {
+        let statements_and_terminator = (0..=body[block].statements.len())
+            .flat_map(|i| (0..3).map(move |j| (i, j)))
+            .map(move |(i, kind)| {
+                let loc = Location { block, statement_index: i };
+                match kind {
+                    0 => SeekTarget::Before(loc),
+                    1 => SeekTarget::After(loc),
+                    2 => SeekTarget::AfterAssumeCallReturns(loc),
+                    _ => unreachable!(),
+                }
+            });
+
+        std::iter::once(SeekTarget::BlockStart(block)).chain(statements_and_terminator)
+    }
+}
+
+#[test]
+fn cursor_seek() {
+    let body = mock_body();
+    let body = &body;
+    let analysis = MockAnalysis { body };
+
+    let mut cursor =
+        Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body);
+
+    // Sanity check: the mock call return effect is unique and actually being applied.
+    let call_terminator_loc = Location { block: BasicBlock::from_usize(2), statement_index: 2 };
+    assert!(is_call_terminator_non_diverging(body, call_terminator_loc));
+
+    let call_return_effect = cursor
+        .analysis()
+        .effect_at_target(SeekTarget::AfterAssumeCallReturns(call_terminator_loc))
+        .unwrap();
+    assert_ne!(
+        call_return_effect,
+        cursor.analysis().effect_at_target(SeekTarget::After(call_terminator_loc)).unwrap()
+    );
+
+    cursor.seek_after(call_terminator_loc);
+    assert!(!cursor.get().contains(call_return_effect));
+    cursor.seek_after_assume_call_returns(call_terminator_loc);
+    assert!(cursor.get().contains(call_return_effect));
+
+    let every_target = || {
+        body.basic_blocks()
+            .iter_enumerated()
+            .flat_map(|(bb, _)| SeekTarget::iter_in_block(body, bb))
+    };
+
+    let mut seek_to_target = |targ| {
+        use SeekTarget::*;
+
+        match targ {
+            BlockStart(block) => cursor.seek_to_block_start(block),
+            Before(loc) => cursor.seek_before(loc),
+            After(loc) => cursor.seek_after(loc),
+            AfterAssumeCallReturns(loc) => cursor.seek_after_assume_call_returns(loc),
+        }
+
+        assert_eq!(cursor.get(), &cursor.analysis().expected_state_at_target(targ));
+    };
+
+    // Seek *to* every possible `SeekTarget` *from* every possible `SeekTarget`.
+    //
+    // By resetting the cursor to `from` each time it changes, we end up checking some edges twice.
+    // What we really want is an Eulerian cycle for the complete digraph over all possible
+    // `SeekTarget`s, but it's not worth spending the time to compute it.
+    for from in every_target() {
+        seek_to_target(from);
+
+        for to in every_target() {
+            seek_to_target(to);
+            seek_to_target(from);
+        }
+    }
+}
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 6597690..63834d0 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -86,10 +86,7 @@
 }
 
 fn find_local(place: &Place<'_>) -> Option<Local> {
-    match place.base {
-        PlaceBase::Local(local) if !place.is_indirect() => Some(local),
-        _ => None,
-    }
+    if !place.is_indirect() { Some(place.local) } else { 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 8d51cb2..f94ee67 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -1,6 +1,6 @@
-use rustc::mir::{self, Body, Location, Place, PlaceBase};
+use rustc::mir::{self, Body, Location, Place};
 use rustc::ty::RegionVid;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::TyCtxt;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
@@ -30,7 +30,6 @@
 pub struct Borrows<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
 
     borrow_set: Rc<BorrowSet<'tcx>>,
     borrows_out_of_scope_at_location: FxHashMap<Location, Vec<BorrowIndex>>,
@@ -134,7 +133,6 @@
     crate fn new(
         tcx: TyCtxt<'tcx>,
         body: &'a Body<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
         nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
         borrow_set: &Rc<BorrowSet<'tcx>>,
     ) -> Self {
@@ -156,7 +154,6 @@
         Borrows {
             tcx,
             body,
-            param_env,
             borrow_set: borrow_set.clone(),
             borrows_out_of_scope_at_location,
             _nonlexical_regioncx: nonlexical_regioncx,
@@ -198,37 +195,34 @@
     fn kill_borrows_on_place(&self, trans: &mut GenKillSet<BorrowIndex>, place: &Place<'tcx>) {
         debug!("kill_borrows_on_place: place={:?}", place);
 
-        if let PlaceBase::Local(local) = place.base {
-            let other_borrows_of_local =
-                self.borrow_set.local_map.get(&local).into_iter().flat_map(|bs| bs.into_iter());
+        let other_borrows_of_local =
+            self.borrow_set.local_map.get(&place.local).into_iter().flat_map(|bs| bs.into_iter());
 
-            // 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_empty() {
-                if !self.body.local_decls[local].is_ref_to_static() {
-                    trans.kill_all(other_borrows_of_local);
-                }
-                return;
+        // 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_empty() {
+            if !self.body.local_decls[place.local].is_ref_to_static() {
+                trans.kill_all(other_borrows_of_local);
             }
-
-            // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
-            // pair of array indices are unequal, so that when `places_conflict` returns true, we
-            // will be assured that two places being compared definitely denotes the same sets of
-            // locations.
-            let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
-                places_conflict(
-                    self.tcx,
-                    self.param_env,
-                    self.body,
-                    &self.borrow_set.borrows[i].borrowed_place,
-                    place,
-                    PlaceConflictBias::NoOverlap,
-                )
-            });
-
-            trans.kill_all(definitely_conflicting_borrows);
+            return;
         }
+
+        // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
+        // pair of array indices are unequal, so that when `places_conflict` returns true, we
+        // will be assured that two places being compared definitely denotes the same sets of
+        // locations.
+        let definitely_conflicting_borrows = other_borrows_of_local.filter(|&&i| {
+            places_conflict(
+                self.tcx,
+                self.body,
+                &self.borrow_set.borrows[i].borrowed_place,
+                place,
+                PlaceConflictBias::NoOverlap,
+            )
+        });
+
+        trans.kill_all(definitely_conflicting_borrows);
     }
 }
 
diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs
index 38401b4..85bf342 100644
--- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs
+++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs
@@ -111,12 +111,8 @@
     fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
         if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
             if self.borrow_allows_mutation(kind, borrowed_place) {
-                match borrowed_place.base {
-                    mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect() => {
-                        self.trans.gen(borrowed_local)
-                    }
-
-                    _ => (),
+                if !borrowed_place.is_indirect() {
+                    self.trans.gen(borrowed_place.local);
                 }
             }
         }
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index 17f71e8..6a48d1e 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -116,15 +116,11 @@
             StatementKind::StorageDead(l) => sets.kill(l),
             StatementKind::Assign(box (ref place, _))
             | StatementKind::SetDiscriminant { box ref place, .. } => {
-                if let PlaceBase::Local(local) = place.base {
-                    sets.gen(local);
-                }
+                sets.gen(place.local);
             }
             StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
-                for p in &**outputs {
-                    if let PlaceBase::Local(local) = p.base {
-                        sets.gen(local);
-                    }
+                for place in &**outputs {
+                    sets.gen(place.local);
                 }
             }
             _ => (),
@@ -140,10 +136,8 @@
     fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
         self.check_for_borrow(sets, loc);
 
-        if let TerminatorKind::Call {
-            destination: Some((Place { base: PlaceBase::Local(local), .. }, _)),
-            ..
-        } = self.body[loc.block].terminator().kind
+        if let TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } =
+            self.body[loc.block].terminator().kind
         {
             sets.gen(local);
         }
@@ -171,9 +165,7 @@
         _dest_bb: mir::BasicBlock,
         dest_place: &mir::Place<'tcx>,
     ) {
-        if let PlaceBase::Local(local) = dest_place.base {
-            in_out.insert(local);
-        }
+        in_out.insert(dest_place.local);
     }
 }
 
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 01f6177..e29730f 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -668,6 +668,26 @@
     const BOTTOM_VALUE: bool;
 
     /// Merges `in_set` into `inout_set`, returning `true` if `inout_set` changed.
+    ///
+    /// It is almost certainly wrong to override this, since it automatically applies
+    /// * `inout_set & in_set` if `BOTTOM_VALUE == true`
+    /// * `inout_set | in_set` if `BOTTOM_VALUE == false`
+    ///
+    /// This means that if a bit is not `BOTTOM_VALUE`, it is propagated into all target blocks.
+    /// For clarity, the above statement again from a different perspective:
+    /// A bit in the block's entry set is `!BOTTOM_VALUE` if *any* predecessor block's bit value is
+    /// `!BOTTOM_VALUE`.
+    ///
+    /// There are situations where you want the opposite behaviour: propagate only if *all*
+    /// predecessor blocks's value is `!BOTTOM_VALUE`.
+    /// E.g. if you want to know whether a bit is *definitely* set at a specific location. This
+    /// means that all code paths leading to the location must have set the bit, instead of any
+    /// code path leading there.
+    ///
+    /// If you want this kind of "definitely set" analysis, you need to
+    /// 1. Invert `BOTTOM_VALUE`
+    /// 2. Reset the `entry_set` in `start_block_effect` to `!BOTTOM_VALUE`
+    /// 3. Override `join` to do the opposite from what it's doing now.
     #[inline]
     fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
         if Self::BOTTOM_VALUE == false {
@@ -685,7 +705,9 @@
 /// for each block individually. The entry set for all other basic blocks is
 /// initialized to `Self::BOTTOM_VALUE`. The dataflow analysis then
 /// iteratively modifies the various entry sets (but leaves the the transfer
-/// function unchanged).
+/// function unchanged). `BottomValue::join` is used to merge the bitsets from
+/// two blocks (e.g. when two blocks' terminator jumps to a single block, that
+/// target block's state is the merged state of both incoming blocks).
 pub trait BitDenotation<'tcx>: BottomValue {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index c05f7f8..271bcce 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -96,12 +96,7 @@
     /// Maybe we should have separate "borrowck" and "moveck" modes.
     fn move_path_for(&mut self, place: &Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
         debug!("lookup({:?})", place);
-        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 = self.builder.data.rev_lookup.locals[place.local];
 
         // The move path index of the first union that we find. Once this is
         // some we stop creating child move paths, since moves from unions
@@ -114,7 +109,7 @@
             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;
+            let place_ty = Place::ty_from(&place.local, proj_base, body, tcx).ty;
             match place_ty.kind {
                 ty::Ref(..) | ty::RawPtr(..) => {
                     let proj = &place.projection[..i + 1];
@@ -122,7 +117,7 @@
                         self.loc,
                         BorrowedContent {
                             target_place: Place {
-                                base: place.base.clone(),
+                                local: place.local,
                                 projection: tcx.intern_place_elems(proj),
                             },
                         },
@@ -163,7 +158,7 @@
 
             if union_path.is_none() {
                 base = self.add_move_path(base, elem, |tcx| Place {
-                    base: place.base.clone(),
+                    local: place.local.clone(),
                     projection: tcx.intern_place_elems(&place.projection[..i + 1]),
                 });
             }
@@ -436,7 +431,7 @@
             // `ConstIndex` patterns. This is done to ensure that all move paths
             // are disjoint, which is expected by drop elaboration.
             let base_place = Place {
-                base: place.base.clone(),
+                local: place.local.clone(),
                 projection: self.builder.tcx.intern_place_elems(base),
             };
             let base_path = match self.move_path_for(&base_place) {
@@ -497,10 +492,10 @@
         // of the union so it is marked as initialized again.
         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.kind
+                Place::ty_from(place.local, proj_base, self.builder.body, self.builder.tcx).ty.kind
             {
                 if def.is_union() {
-                    place = PlaceRef { base: place.base, projection: proj_base }
+                    place = PlaceRef { local: place.local, projection: proj_base }
                 }
             }
         }
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index e5cddaf..a46465a 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -246,10 +246,7 @@
     // unknown place, but will rather return the nearest available
     // parent.
     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),
-        };
+        let mut result = self.locals[*place.local];
 
         for elem in place.projection.iter() {
             if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
@@ -281,9 +278,6 @@
 
 #[derive(Debug)]
 pub(crate) enum IllegalMoveOriginKind<'tcx> {
-    /// Illegal move due to attempt to move from `static` variable.
-    Static,
-
     /// Illegal move due to attempt to move from behind a reference.
     BorrowedContent {
         /// The place the reference refers to: if erroneous code was trying to
diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs
deleted file mode 100644
index a4bedfa..0000000
--- a/src/librustc_mir/hair/constant.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-use rustc::mir::interpret::{ConstValue, Scalar};
-use rustc::ty::{self, layout::Size, ParamEnv, Ty, TyCtxt};
-use rustc_span::symbol::Symbol;
-use syntax::ast;
-
-#[derive(PartialEq)]
-crate enum LitToConstError {
-    UnparseableFloat,
-    Reported,
-}
-
-crate fn lit_to_const<'tcx>(
-    lit: &'tcx ast::LitKind,
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-    neg: bool,
-) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
-    use syntax::ast::*;
-
-    let trunc = |n| {
-        let param_ty = ParamEnv::reveal_all().and(ty);
-        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
-        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
-        let result = truncate(n, width);
-        trace!("trunc result: {}", result);
-        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
-    };
-
-    use rustc::mir::interpret::*;
-    let lit = match *lit {
-        LitKind::Str(ref s, _) => {
-            let s = s.as_str();
-            let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
-        }
-        LitKind::ByteStr(ref data) => {
-            let id = tcx.allocate_bytes(data);
-            ConstValue::Scalar(Scalar::Ptr(id.into()))
-        }
-        LitKind::Byte(n) => ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))),
-        LitKind::Int(n, _) if neg => {
-            let n = n as i128;
-            let n = n.overflowing_neg().0;
-            trunc(n as u128)?
-        }
-        LitKind::Int(n, _) => trunc(n)?,
-        LitKind::Float(n, _) => {
-            let fty = match ty.kind {
-                ty::Float(fty) => fty,
-                _ => bug!(),
-            };
-            parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
-        }
-        LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
-        LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
-        LitKind::Err(_) => unreachable!(),
-    };
-    Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(lit), ty }))
-}
-
-fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result<ConstValue<'tcx>, ()> {
-    let num = num.as_str();
-    use rustc_apfloat::ieee::{Double, Single};
-    let scalar = match fty {
-        ast::FloatTy::F32 => {
-            num.parse::<f32>().map_err(|_| ())?;
-            let mut f = num.parse::<Single>().unwrap_or_else(|e| {
-                panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
-            });
-            if neg {
-                f = -f;
-            }
-            Scalar::from_f32(f)
-        }
-        ast::FloatTy::F64 => {
-            num.parse::<f64>().map_err(|_| ())?;
-            let mut f = num.parse::<Double>().unwrap_or_else(|e| {
-                panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
-            });
-            if neg {
-                f = -f;
-            }
-            Scalar::from_f64(f)
-        }
-    };
-
-    Ok(ConstValue::Scalar(scalar))
-}
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 551e3e8..206d3d1 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -20,7 +20,7 @@
 use rustc_span::source_map::{self, Span, DUMMY_SP};
 
 use super::{
-    Immediate, MPlaceTy, Machine, MemPlace, Memory, OpTy, Operand, Place, PlaceTy,
+    Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
     ScalarMaybeUndef, StackPopInfo,
 };
 
@@ -393,7 +393,7 @@
     /// This can fail to provide an answer for extern types.
     pub(super) fn size_and_align_of(
         &self,
-        metadata: Option<Scalar<M::PointerTag>>,
+        metadata: MemPlaceMeta<M::PointerTag>,
         layout: TyLayout<'tcx>,
     ) -> InterpResult<'tcx, Option<(Size, Align)>> {
         if !layout.is_unsized() {
@@ -465,14 +465,13 @@
                 Ok(Some((size, align)))
             }
             ty::Dynamic(..) => {
-                let vtable = metadata.expect("dyn trait fat ptr must have vtable");
+                let vtable = metadata.unwrap_meta();
                 // 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 length").to_machine_usize(self)?;
+                let len = metadata.unwrap_meta().to_machine_usize(self)?;
                 let elem = layout.field(self, 0)?;
 
                 // Make sure the slice is not too big.
@@ -758,13 +757,22 @@
         &self,
         gid: GlobalId<'tcx>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let val = if self.tcx.is_static(gid.instance.def_id()) {
-            self.tcx.const_eval_poly(gid.instance.def_id())?
-        } else if let Some(promoted) = gid.promoted {
-            self.tcx.const_eval_promoted(gid.instance, promoted)?
+        // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
+        // and thus don't care about the parameter environment. While we could just use
+        // `self.param_env`, that would mean we invoke the query to evaluate the static
+        // with different parameter environments, thus causing the static to be evaluated
+        // multiple times.
+        let param_env = if self.tcx.is_static(gid.instance.def_id()) {
+            ty::ParamEnv::reveal_all()
         } else {
-            self.tcx.const_eval_instance(self.param_env, gid.instance, Some(self.tcx.span))?
+            self.param_env
         };
+        let val = if let Some(promoted) = gid.promoted {
+            self.tcx.const_eval_promoted(param_env, gid.instance, promoted)?
+        } else {
+            self.tcx.const_eval_instance(param_env, gid.instance, Some(self.tcx.span))?
+        };
+
         // Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
         // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
         // return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
@@ -818,8 +826,8 @@
                                 " by align({}){} ref:",
                                 mplace.align.bytes(),
                                 match mplace.meta {
-                                    Some(meta) => format!(" meta({:?})", meta),
-                                    None => String::new(),
+                                    MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
+                                    MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
                                 }
                             )
                             .unwrap();
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 7c6129e..0c65b77 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -41,6 +41,11 @@
     /// despite the nested mutable reference!
     /// The field gets updated when an `UnsafeCell` is encountered.
     mutability: Mutability,
+
+    /// This flag is to avoid triggering UnsafeCells are not allowed behind references in constants
+    /// for promoteds.
+    /// It's a copy of `mir::Body`'s ignore_interior_mut_in_const_validation field
+    ignore_interior_mut_in_const_validation: bool,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
@@ -164,14 +169,16 @@
                 // References we encounter inside here are interned as pointing to mutable
                 // allocations.
                 let old = std::mem::replace(&mut self.mutability, Mutability::Mut);
-                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 could \
-                    observe that mutation.",
-                );
+                if !self.ignore_interior_mut_in_const_validation {
+                    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 could observe that mutation.",
+                    );
+                }
                 let walked = self.walk_aggregate(mplace, fields);
                 self.mutability = old;
                 return walked;
@@ -193,7 +200,7 @@
             {
                 // Validation has already errored on an invalid vtable pointer so we can safely not
                 // do anything if this is not a real pointer.
-                if let Scalar::Ptr(vtable) = mplace.meta.unwrap() {
+                if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() {
                     // Explicitly choose `Immutable` here, since vtables are immutable, even
                     // if the reference of the fat pointer is mutable.
                     self.intern_shallow(vtable.alloc_id, Mutability::Not, None)?;
@@ -226,7 +233,8 @@
                     | (InternMode::Const, hir::Mutability::Mut) => match referenced_ty.kind {
                         ty::Array(_, n)
                             if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
-                        ty::Slice(_) if mplace.meta.unwrap().to_machine_usize(self.ecx)? == 0 => {}
+                        ty::Slice(_)
+                            if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? == 0 => {}
                         _ => bug!("const qualif failed to prevent mutable references"),
                     },
                 }
@@ -260,18 +268,27 @@
     }
 }
 
+pub enum InternKind {
+    /// The `mutability` of the static, ignoring the type which may have interior mutability.
+    Static(hir::Mutability),
+    Constant,
+    Promoted,
+    ConstProp,
+}
+
 pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
     ecx: &mut InterpCx<'mir, 'tcx, M>,
-    // The `mutability` of the place, ignoring the type.
-    place_mut: Option<hir::Mutability>,
+    intern_kind: InternKind,
     ret: MPlaceTy<'tcx>,
+    ignore_interior_mut_in_const_validation: bool,
 ) -> InterpResult<'tcx> {
     let tcx = ecx.tcx;
-    let (base_mutability, base_intern_mode) = match place_mut {
+    let (base_mutability, base_intern_mode) = match intern_kind {
         // `static mut` doesn't care about interior mutability, it's mutable anyway
-        Some(mutbl) => (mutbl, InternMode::Static),
-        // consts, promoteds. FIXME: what about array lengths, array initializers?
-        None => (Mutability::Not, InternMode::ConstBase),
+        InternKind::Static(mutbl) => (mutbl, InternMode::Static),
+        // FIXME: what about array lengths, array initializers?
+        InternKind::Constant | InternKind::ConstProp => (Mutability::Not, InternMode::ConstBase),
+        InternKind::Promoted => (Mutability::Not, InternMode::ConstBase),
     };
 
     // Type based interning.
@@ -301,6 +318,7 @@
             mode,
             leftover_allocations,
             mutability,
+            ignore_interior_mut_in_const_validation,
         }
         .visit_value(mplace);
         if let Err(error) = interned {
@@ -328,10 +346,24 @@
             // 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.
-            match base_intern_mode {
-                InternMode::Static => {}
-                InternMode::Const | InternMode::ConstBase => {
-                    // If it's not a static, it *must* be immutable.
+            match intern_kind {
+                // Statics may contain mutable allocations even behind relocations.
+                // Even for immutable statics it would be ok to have mutable allocations behind
+                // raw pointers, e.g. for `static FOO: *const AtomicUsize = &AtomicUsize::new(42)`.
+                InternKind::Static(_) => {}
+                // Raw pointers in promoteds may only point to immutable things so we mark
+                // everything as immutable.
+                // It is UB to mutate through a raw pointer obtained via an immutable reference.
+                // Since all references and pointers inside a promoted must by their very definition
+                // be created from an immutable reference (and promotion also excludes interior
+                // mutability), mutating through them would be UB.
+                // There's no way we can check whether the user is using raw pointers correctly,
+                // so all we can do is mark this as immutable here.
+                InternKind::Promoted => {
+                    alloc.mutability = Mutability::Not;
+                }
+                InternKind::Constant | InternKind::ConstProp => {
+                    // If it's a constant, it *must* be immutable.
                     // We cannot have mutable memory inside a constant.
                     // We use `delay_span_bug` here, because this can be reached in the presence
                     // of fancy transmutes.
@@ -354,6 +386,8 @@
             // dangling pointer
             throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
         } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() {
+            // We have hit an `AllocId` that is neither in local or global memory and isn't marked
+            // as dangling by local memory.
             span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
         }
     }
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index eed47c1..cd8bf70 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -69,9 +69,8 @@
         }
     }
 
-    fn print_const(self, _: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
-        // don't print constants to the user
-        Ok(self)
+    fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+        self.pretty_print_const(ct, false)
     }
 
     fn print_dyn_existential(
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 6d15827..3309e9b 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -212,7 +212,7 @@
         frame.locals[local].access()
     }
 
-    /// Called before a `StaticKind::Static` value is accessed.
+    /// Called before a `Static` value is accessed.
     fn before_access_static(
         _memory_extra: &Self::MemoryExtra,
         _allocation: &Allocation,
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index cb67682..0bcdf9a 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -580,10 +580,9 @@
                 let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
                 Ok((layout.size, layout.align.abi))
             }
-            Some(GlobalAlloc::Memory(alloc)) =>
-            // Need to duplicate the logic here, because the global allocations have
-            // different associated types than the interpreter-local ones.
-            {
+            Some(GlobalAlloc::Memory(alloc)) => {
+                // Need to duplicate the logic here, because the global allocations have
+                // different associated types than the interpreter-local ones.
                 Ok((alloc.size, alloc.align))
             }
             Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 0d35eae..a519f38 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -20,7 +20,7 @@
 
 pub use self::eval_context::{Frame, InterpCx, LocalState, LocalValue, StackPopCleanup};
 
-pub use self::place::{MPlaceTy, MemPlace, Place, PlaceTy};
+pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
 
 pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind};
 
@@ -32,6 +32,6 @@
 
 pub use self::validity::RefTracking;
 
-pub use self::intern::intern_const_alloc_recursive;
+pub use self::intern::{intern_const_alloc_recursive, InternKind};
 
 crate use self::intrinsics::eval_nullary_intrinsic;
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index def979b..d1c08da 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -153,30 +153,6 @@
     Indirect(MemPlace<Tag, Id>),
 }
 
-impl<Tag> Operand<Tag> {
-    #[inline]
-    pub fn assert_mem_place(self) -> MemPlace<Tag>
-    where
-        Tag: ::std::fmt::Debug,
-    {
-        match self {
-            Operand::Indirect(mplace) => mplace,
-            _ => bug!("assert_mem_place: expected Operand::Indirect, got {:?}", self),
-        }
-    }
-
-    #[inline]
-    pub fn assert_immediate(self) -> Immediate<Tag>
-    where
-        Tag: ::std::fmt::Debug,
-    {
-        match self {
-            Operand::Immediate(imm) => imm,
-            _ => bug!("assert_immediate: expected Operand::Immediate, got {:?}", self),
-        }
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct OpTy<'tcx, Tag = ()> {
     op: Operand<Tag>, // Keep this private; it helps enforce invariants.
@@ -267,7 +243,7 @@
         &self,
         op: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        match op.try_as_mplace() {
+        match op.try_as_mplace(self) {
             Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
             Err(imm) => Ok(imm.into()), // Nothing to cast/force
         }
@@ -335,7 +311,7 @@
         &self,
         src: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> {
-        Ok(match src.try_as_mplace() {
+        Ok(match src.try_as_mplace(self) {
             Ok(mplace) => {
                 if let Some(val) = self.try_read_immediate_from_mplace(mplace)? {
                     Ok(val)
@@ -383,7 +359,7 @@
         op: OpTy<'tcx, M::PointerTag>,
         field: u64,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let base = match op.try_as_mplace() {
+        let base = match op.try_as_mplace(self) {
             Ok(mplace) => {
                 // The easy case
                 let field = self.mplace_field(mplace, field)?;
@@ -420,7 +396,7 @@
         variant: VariantIdx,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        Ok(match op.try_as_mplace() {
+        Ok(match op.try_as_mplace(self) {
             Ok(mplace) => self.mplace_downcast(mplace, variant)?.into(),
             Err(..) => {
                 let layout = op.layout.for_variant(self, variant);
@@ -439,30 +415,10 @@
             Field(field, _) => self.operand_field(base, field.index() as u64)?,
             Downcast(_, variant) => self.operand_downcast(base, variant)?,
             Deref => self.deref_operand(base)?.into(),
-            ConstantIndex { .. } | Index(_) if base.layout.is_zst() => {
-                OpTy {
-                    op: Operand::Immediate(Scalar::zst().into()),
-                    // the actual index doesn't matter, so we just pick a convenient one like 0
-                    layout: base.layout.field(self, 0)?,
-                }
-            }
-            Subslice { from, to, from_end } if base.layout.is_zst() => {
-                let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind {
-                    elem_ty
-                } else {
-                    bug!("slices shouldn't be zero-sized");
-                };
-                assert!(!from_end, "arrays shouldn't be subsliced from the end");
-
-                OpTy {
-                    op: Operand::Immediate(Scalar::zst().into()),
-                    layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?,
-                }
-            }
             Subslice { .. } | ConstantIndex { .. } | Index(_) => {
                 // The rest should only occur as mplace, we do not use Immediates for types
                 // allowing such operations.  This matches place_projection forcing an allocation.
-                let mplace = base.assert_mem_place();
+                let mplace = base.assert_mem_place(self);
                 self.mplace_projection(mplace, proj_elem)?.into()
             }
         })
@@ -506,19 +462,15 @@
         place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        use rustc::mir::PlaceBase;
-
-        let base_op = match &place.base {
-            PlaceBase::Local(mir::RETURN_PLACE) => throw_unsup!(ReadFromReturnPointer),
-            PlaceBase::Local(local) => {
+        let base_op = match place.local {
+            mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer),
+            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)?
+                self.access_local(self.frame(), local, layout)?
             }
-            PlaceBase::Static(place_static) => self.eval_static_to_mplace(&place_static)?.into(),
         };
 
         let op = place
@@ -576,7 +528,7 @@
         // Early-return cases.
         let val_val = match val.val {
             ty::ConstKind::Param(_) => throw_inval!(TooGeneric),
-            ty::ConstKind::Unevaluated(def_id, substs) => {
+            ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 let instance = self.resolve(def_id, substs)?;
                 // We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
                 // The reason we use `const_eval_raw` everywhere else is to prevent cycles during
@@ -584,9 +536,7 @@
                 // potentially requiring the current static to be evaluated again. This is not a
                 // problem here, because we are building an operand which means an actual read is
                 // happening.
-                // FIXME(oli-obk): eliminate all the `const_eval_raw` usages when we get rid of
-                // `StaticKind` once and for all.
-                return self.const_eval(GlobalId { instance, promoted: None });
+                return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?));
             }
             ty::ConstKind::Infer(..)
             | ty::ConstKind::Bound(..)
@@ -734,16 +684,14 @@
                             let variant_index = variants_start
                                 .checked_add(variant_index_relative)
                                 .expect("oveflow computing absolute variant idx");
-                            assert!(
-                                (variant_index as usize)
-                                    < rval
-                                        .layout
-                                        .ty
-                                        .ty_adt_def()
-                                        .expect("tagged layout for non adt")
-                                        .variants
-                                        .len()
-                            );
+                            let variants_len = rval
+                                .layout
+                                .ty
+                                .ty_adt_def()
+                                .expect("tagged layout for non adt")
+                                .variants
+                                .len();
+                            assert!((variant_index as usize) < variants_len);
                             (u128::from(variant_index), VariantIdx::from_u32(variant_index))
                         } else {
                             (u128::from(dataful_variant.as_u32()), dataful_variant)
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index f4ac7de..4f96cb6 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -10,17 +10,57 @@
 use rustc::ty::layout::{
     self, Align, HasDataLayout, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
 };
-use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty};
 use rustc_macros::HashStable;
 
 use super::{
-    AllocId, AllocMap, Allocation, AllocationExtra, GlobalId, ImmTy, Immediate, InterpCx,
-    InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer, PointerArithmetic,
-    RawConst, Scalar, ScalarMaybeUndef,
+    AllocId, AllocMap, Allocation, AllocationExtra, ImmTy, Immediate, InterpCx, InterpResult,
+    LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer, PointerArithmetic, RawConst, Scalar,
+    ScalarMaybeUndef,
 };
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
+/// Information required for the sound usage of a `MemPlace`.
+pub enum MemPlaceMeta<Tag = (), Id = AllocId> {
+    /// The unsized payload (e.g. length for slices or vtable pointer for trait objects).
+    Meta(Scalar<Tag, Id>),
+    /// `Sized` types or unsized `extern type`
+    None,
+    /// The address of this place may not be taken. This protects the `MemPlace` from coming from
+    /// a ZST Operand with a backing allocation and being converted to an integer address. This
+    /// should be impossible, because you can't take the address of an operand, but this is a second
+    /// protection layer ensuring that we don't mess up.
+    Poison,
+}
+
+impl<Tag, Id> MemPlaceMeta<Tag, Id> {
+    pub fn unwrap_meta(self) -> Scalar<Tag, Id> {
+        match self {
+            Self::Meta(s) => s,
+            Self::None | Self::Poison => {
+                bug!("expected wide pointer extra data (e.g. slice length or trait object vtable)")
+            }
+        }
+    }
+    fn has_meta(self) -> bool {
+        match self {
+            Self::Meta(_) => true,
+            Self::None | Self::Poison => false,
+        }
+    }
+}
+
+impl<Tag> MemPlaceMeta<Tag> {
+    pub fn erase_tag(self) -> MemPlaceMeta<()> {
+        match self {
+            Self::Meta(s) => MemPlaceMeta::Meta(s.erase_tag()),
+            Self::None => MemPlaceMeta::None,
+            Self::Poison => MemPlaceMeta::Poison,
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
 pub struct MemPlace<Tag = (), Id = AllocId> {
     /// A place may have an integral pointer for ZSTs, and since it might
     /// be turned back into a reference before ever being dereferenced.
@@ -30,7 +70,7 @@
     /// Metadata for unsized places. Interpretation is up to the type.
     /// Must not be present for sized types, but can be missing for unsized types
     /// (e.g., `extern type`).
-    pub meta: Option<Scalar<Tag, Id>>,
+    pub meta: MemPlaceMeta<Tag, Id>,
 }
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
@@ -88,21 +128,17 @@
 
     #[inline]
     pub fn erase_tag(self) -> MemPlace {
-        MemPlace {
-            ptr: self.ptr.erase_tag(),
-            align: self.align,
-            meta: self.meta.map(Scalar::erase_tag),
-        }
+        MemPlace { ptr: self.ptr.erase_tag(), align: self.align, meta: self.meta.erase_tag() }
     }
 
     #[inline(always)]
-    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
-        MemPlace { ptr, align, meta: None }
+    fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
+        MemPlace { ptr, align, meta: MemPlaceMeta::None }
     }
 
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline(always)]
-    pub fn null(cx: &impl HasDataLayout) -> Self {
+    fn null(cx: &impl HasDataLayout) -> Self {
         Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1).unwrap())
     }
 
@@ -116,15 +152,19 @@
     #[inline(always)]
     pub fn to_ref(self) -> Immediate<Tag> {
         match self.meta {
-            None => Immediate::Scalar(self.ptr.into()),
-            Some(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()),
+            MemPlaceMeta::None => Immediate::Scalar(self.ptr.into()),
+            MemPlaceMeta::Meta(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()),
+            MemPlaceMeta::Poison => bug!(
+                "MPlaceTy::dangling may never be used to produce a \
+                place that will have the address of its pointee taken"
+            ),
         }
     }
 
     pub fn offset(
         self,
         offset: Size,
-        meta: Option<Scalar<Tag>>,
+        meta: MemPlaceMeta<Tag>,
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx, Self> {
         Ok(MemPlace {
@@ -139,13 +179,10 @@
     /// Produces a MemPlace that works for ZST but nothing else
     #[inline]
     pub fn dangling(layout: TyLayout<'tcx>, cx: &impl HasDataLayout) -> Self {
-        MPlaceTy {
-            mplace: MemPlace::from_scalar_ptr(
-                Scalar::from_uint(layout.align.abi.bytes(), cx.pointer_size()),
-                layout.align.abi,
-            ),
-            layout,
-        }
+        let align = layout.align.abi;
+        let ptr = Scalar::from_uint(align.bytes(), cx.pointer_size());
+        // `Poison` this to make sure that the pointer value `ptr` is never observable by the program.
+        MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout }
     }
 
     /// Replace ptr tag, maintain vtable tag (if any)
@@ -158,7 +195,7 @@
     pub fn offset(
         self,
         offset: Size,
-        meta: Option<Scalar<Tag>>,
+        meta: MemPlaceMeta<Tag>,
         layout: TyLayout<'tcx>,
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx, Self> {
@@ -175,7 +212,9 @@
         if self.layout.is_unsized() {
             // We need to consult `meta` metadata
             match self.layout.ty.kind {
-                ty::Slice(..) | ty::Str => return self.mplace.meta.unwrap().to_machine_usize(cx),
+                ty::Slice(..) | ty::Str => {
+                    return self.mplace.meta.unwrap_meta().to_machine_usize(cx);
+                }
                 _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
             }
         } else {
@@ -191,7 +230,7 @@
     #[inline]
     pub(super) fn vtable(self) -> Scalar<Tag> {
         match self.layout.ty.kind {
-            ty::Dynamic(..) => self.mplace.meta.unwrap(),
+            ty::Dynamic(..) => self.mplace.meta.unwrap_meta(),
             _ => bug!("vtable not supported on type {:?}", self.layout.ty),
         }
     }
@@ -200,36 +239,36 @@
 // These are defined here because they produce a place.
 impl<'tcx, Tag: ::std::fmt::Debug + Copy> OpTy<'tcx, Tag> {
     #[inline(always)]
-    pub fn try_as_mplace(self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
+    /// Note: do not call `as_ref` on the resulting place. This function should only be used to
+    /// read from the resulting mplace, not to get its address back.
+    pub fn try_as_mplace(
+        self,
+        cx: &impl HasDataLayout,
+    ) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
         match *self {
             Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
+            Operand::Immediate(_) if self.layout.is_zst() => {
+                Ok(MPlaceTy::dangling(self.layout, cx))
+            }
             Operand::Immediate(imm) => Err(ImmTy { imm, layout: self.layout }),
         }
     }
 
     #[inline(always)]
-    pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> {
-        self.try_as_mplace().unwrap()
+    /// Note: do not call `as_ref` on the resulting place. This function should only be used to
+    /// read from the resulting mplace, not to get its address back.
+    pub fn assert_mem_place(self, cx: &impl HasDataLayout) -> MPlaceTy<'tcx, Tag> {
+        self.try_as_mplace(cx).unwrap()
     }
 }
 
 impl<Tag: ::std::fmt::Debug> Place<Tag> {
     /// Produces a Place that will error if attempted to be read from or written to
     #[inline(always)]
-    pub fn null(cx: &impl HasDataLayout) -> Self {
+    fn null(cx: &impl HasDataLayout) -> Self {
         Place::Ptr(MemPlace::null(cx))
     }
 
-    #[inline(always)]
-    pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
-        Place::Ptr(MemPlace::from_scalar_ptr(ptr, align))
-    }
-
-    #[inline(always)]
-    pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
-        Place::Ptr(MemPlace::from_ptr(ptr, align))
-    }
-
     #[inline]
     pub fn assert_mem_place(self) -> MemPlace<Tag> {
         match self {
@@ -270,8 +309,10 @@
             val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
         let layout = self.layout_of(pointee_type)?;
         let (ptr, meta) = match *val {
-            Immediate::Scalar(ptr) => (ptr.not_undef()?, None),
-            Immediate::ScalarPair(ptr, meta) => (ptr.not_undef()?, Some(meta.not_undef()?)),
+            Immediate::Scalar(ptr) => (ptr.not_undef()?, MemPlaceMeta::None),
+            Immediate::ScalarPair(ptr, meta) => {
+                (ptr.not_undef()?, MemPlaceMeta::Meta(meta.not_undef()?))
+            }
         };
 
         let mplace = MemPlace {
@@ -305,14 +346,14 @@
     /// On success, returns `None` for zero-sized accesses (where nothing else is
     /// left to do) and a `Pointer` to use for the actual access otherwise.
     #[inline]
-    pub fn check_mplace_access(
+    pub(super) fn check_mplace_access(
         &self,
         place: MPlaceTy<'tcx, M::PointerTag>,
         size: Option<Size>,
     ) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
         let size = size.unwrap_or_else(|| {
             assert!(!place.layout.is_unsized());
-            assert!(place.meta.is_none());
+            assert!(!place.meta.has_meta());
             place.layout.size
         });
         self.memory.check_ptr_access(place.ptr, size, place.align)
@@ -338,7 +379,7 @@
 
     /// Force `place.ptr` to a `Pointer`.
     /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
-    pub fn force_mplace_ptr(
+    pub(super) fn force_mplace_ptr(
         &self,
         mut place: MPlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
@@ -391,12 +432,11 @@
             // happens at run-time so that's okay.
             let align = match self.size_and_align_of(base.meta, field_layout)? {
                 Some((_, align)) => align,
-                None if offset == Size::ZERO =>
-                // An extern type at offset 0, we fall back to its static alignment.
-                // FIXME: Once we have made decisions for how to handle size and alignment
-                // of `extern type`, this should be adapted.  It is just a temporary hack
-                // to get some code to work that probably ought to work.
-                {
+                None if offset == Size::ZERO => {
+                    // An extern type at offset 0, we fall back to its static alignment.
+                    // FIXME: Once we have made decisions for how to handle size and alignment
+                    // of `extern type`, this should be adapted.  It is just a temporary hack
+                    // to get some code to work that probably ought to work.
                     field_layout.align.abi
                 }
                 None => bug!("Cannot compute offset for extern type field at non-0 offset"),
@@ -405,7 +445,7 @@
         } else {
             // base.meta could be present; we might be accessing a sized field of an unsized
             // struct.
-            (None, offset)
+            (MemPlaceMeta::None, offset)
         };
 
         // We do not look at `base.layout.align` nor `field_layout.align`, unlike
@@ -415,7 +455,7 @@
 
     // Iterates over all fields of an array. Much more efficient than doing the
     // same by repeatedly calling `mplace_array`.
-    pub fn mplace_array_fields(
+    pub(super) fn mplace_array_fields(
         &self,
         base: MPlaceTy<'tcx, Tag>,
     ) -> InterpResult<'tcx, impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Tag>>> + 'tcx>
@@ -427,10 +467,10 @@
         };
         let layout = base.layout.field(self, 0)?;
         let dl = &self.tcx.data_layout;
-        Ok((0..len).map(move |i| base.offset(i * stride, None, layout, dl)))
+        Ok((0..len).map(move |i| base.offset(i * stride, MemPlaceMeta::None, layout, dl)))
     }
 
-    pub fn mplace_subslice(
+    fn mplace_subslice(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
         from: u64,
@@ -460,10 +500,10 @@
         let (meta, ty) = match base.layout.ty.kind {
             // It is not nice to match on the type, but that seems to be the only way to
             // implement this.
-            ty::Array(inner, _) => (None, self.tcx.mk_array(inner, inner_len)),
+            ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(inner, inner_len)),
             ty::Slice(..) => {
                 let len = Scalar::from_uint(inner_len, self.pointer_size());
-                (Some(len), base.layout.ty)
+                (MemPlaceMeta::Meta(len), base.layout.ty)
             }
             _ => bug!("cannot subslice non-array type: `{:?}`", base.layout.ty),
         };
@@ -471,18 +511,18 @@
         base.offset(from_offset, meta, layout, self)
     }
 
-    pub fn mplace_downcast(
+    pub(super) fn mplace_downcast(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
         variant: VariantIdx,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
-        assert!(base.meta.is_none());
+        assert!(!base.meta.has_meta());
         Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..base })
     }
 
     /// Project into an mplace
-    pub fn mplace_projection(
+    pub(super) fn mplace_projection(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
         proj_elem: &mir::PlaceElem<'tcx>,
@@ -577,64 +617,14 @@
         })
     }
 
-    /// Evaluate statics and promoteds to an `MPlace`. Used to share some code between
-    /// `eval_place` and `eval_place_to_op`.
-    pub(super) fn eval_static_to_mplace(
-        &self,
-        place_static: &mir::Static<'tcx>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        use rustc::mir::StaticKind;
-
-        Ok(match place_static.kind {
-            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);
-
-                // Even after getting `substs` from the frame, this instance may still be
-                // polymorphic because `ConstProp` will try to promote polymorphic MIR.
-                if instance.needs_subst() {
-                    throw_inval!(TooGeneric);
-                }
-
-                self.const_eval_raw(GlobalId { instance, promoted: Some(promoted) })?
-            }
-
-            StaticKind::Static => {
-                let ty = place_static.ty;
-                assert!(!ty.needs_subst());
-                let layout = self.layout_of(ty)?;
-                // Just create a lazy reference, so we can support recursive statics.
-                // tcx takes care of assigning every static one and only one unique AllocId.
-                // When the data here is ever actually used, memory will notice,
-                // and it knows how to deal with alloc_id that are present in the
-                // global table but not in its local memory: It calls back into tcx through
-                // a query, triggering the CTFE machinery to actually turn this lazy reference
-                // into a bunch of bytes.  IOW, statics are evaluated with CTFE even when
-                // this InterpCx uses another Machine (e.g., in miri).  This is what we
-                // want!  This way, computing statics works consistently between codegen
-                // and miri: They use the same query to eventually obtain a `ty::Const`
-                // and use that for further computation.
-                //
-                // Notice that statics have *two* AllocIds: the lazy one, and the resolved
-                // one.  Here we make sure that the interpreted program never sees the
-                // resolved ID.  Also see the doc comment of `Memory::get_static_alloc`.
-                let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(place_static.def_id);
-                let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id));
-                MPlaceTy::from_aligned_ptr(ptr, layout)
-            }
-        })
-    }
-
     /// Computes a place. You should only use this if you intend to write into this
     /// place; for reading, a more efficient alternative is `eval_place_for_read`.
     pub fn eval_place(
         &mut self,
         place: &mir::Place<'tcx>,
     ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
-        use rustc::mir::PlaceBase;
-
-        let mut place_ty = match &place.base {
-            PlaceBase::Local(mir::RETURN_PLACE) => {
+        let mut place_ty = match place.local {
+            mir::RETURN_PLACE => {
                 // `return_place` has the *caller* layout, but we want to use our
                 // `layout to verify our assumption. The caller will validate
                 // their layout on return.
@@ -655,12 +645,11 @@
                     ))?,
                 }
             }
-            PlaceBase::Local(local) => PlaceTy {
+            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)?,
+                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(),
         };
 
         for elem in place.projection.iter() {
@@ -971,7 +960,7 @@
     pub fn force_allocation_maybe_sized(
         &mut self,
         place: PlaceTy<'tcx, M::PointerTag>,
-        meta: Option<Scalar<M::PointerTag>>,
+        meta: MemPlaceMeta<M::PointerTag>,
     ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option<Size>)> {
         let (mplace, size) = match place.place {
             Place::Local { frame, local } => {
@@ -1016,7 +1005,7 @@
         &mut self,
         place: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        Ok(self.force_allocation_maybe_sized(place, None)?.0)
+        Ok(self.force_allocation_maybe_sized(place, MemPlaceMeta::None)?.0)
     }
 
     pub fn allocate(
@@ -1036,8 +1025,11 @@
     ) -> MPlaceTy<'tcx, M::PointerTag> {
         let ptr = self.memory.allocate_static_bytes(str.as_bytes(), kind);
         let meta = Scalar::from_uint(str.len() as u128, self.pointer_size());
-        let mplace =
-            MemPlace { ptr: ptr.into(), align: Align::from_bytes(1).unwrap(), meta: Some(meta) };
+        let mplace = MemPlace {
+            ptr: ptr.into(),
+            align: Align::from_bytes(1).unwrap(),
+            meta: MemPlaceMeta::Meta(meta),
+        };
 
         let layout = self.layout_of(self.tcx.mk_static_str()).unwrap();
         MPlaceTy { mplace, layout }
@@ -1145,7 +1137,7 @@
             assert_eq!(align, layout.align.abi);
         }
 
-        let mplace = MPlaceTy { mplace: MemPlace { meta: None, ..*mplace }, layout };
+        let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..*mplace }, layout };
         Ok((instance, mplace))
     }
 }
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 6790baf..a8e67c8 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -23,7 +23,9 @@
 use syntax::ast::Mutability;
 
 use super::eval_context::{LocalState, StackPopCleanup};
-use super::{Frame, Immediate, LocalValue, MemPlace, Memory, Operand, Place, ScalarMaybeUndef};
+use super::{
+    Frame, Immediate, LocalValue, MemPlace, MemPlaceMeta, Memory, Operand, Place, ScalarMaybeUndef,
+};
 use crate::const_eval::CompileTimeInterpreter;
 
 #[derive(Default)]
@@ -205,6 +207,14 @@
     }
 );
 
+impl_snapshot_for!(
+    enum MemPlaceMeta {
+        Meta(s),
+        None,
+        Poison,
+    }
+);
+
 impl_snapshot_for!(struct MemPlace {
     ptr,
     meta,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index a28bb53..37dcab5 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -378,7 +378,7 @@
                     }
                     None => {
                         // Unsized self.
-                        args[0].assert_mem_place()
+                        args[0].assert_mem_place(self)
                     }
                 };
                 // Find and consult vtable
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 7b82bed..aa2b304 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -16,7 +16,7 @@
 use std::hash::Hash;
 
 use super::{
-    CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Scalar,
+    CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
     ValueVisitor,
 };
 
@@ -114,14 +114,11 @@
             ClosureVar(name) => write!(out, ".<closure-var({})>", name),
             TupleElem(idx) => write!(out, ".{}", idx),
             ArrayElem(idx) => write!(out, "[{}]", idx),
-            Deref =>
-            // This does not match Rust syntax, but it is more readable for long paths -- and
+            // `.<deref>` does not match Rust syntax, but it is more readable for long paths -- and
             // some of the other items here also are not Rust syntax.  Actually we can't
             // even use the usual syntax because we are just showing the projections,
             // not the root.
-            {
-                write!(out, ".<deref>")
-            }
+            Deref => write!(out, ".<deref>"),
             Tag => write!(out, ".<enum-tag>"),
             DynDowncast => write!(out, ".<dyn-downcast>"),
         }
@@ -206,9 +203,8 @@
             ty::Adt(def, ..) if def.is_enum() => {
                 // we might be projecting *to* a variant, or to a field *in*a variant.
                 match layout.variants {
-                    layout::Variants::Single { index } =>
-                    // Inside a variant
-                    {
+                    layout::Variants::Single { index } => {
+                        // Inside a variant
                         PathElem::Field(def.variants[index].fields[field].ident.name)
                     }
                     _ => bug!(),
@@ -246,13 +242,13 @@
 
     fn check_wide_ptr_meta(
         &mut self,
-        meta: Option<Scalar<M::PointerTag>>,
+        meta: MemPlaceMeta<M::PointerTag>,
         pointee: TyLayout<'tcx>,
     ) -> InterpResult<'tcx> {
         let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
         match tail.kind {
             ty::Dynamic(..) => {
-                let vtable = meta.unwrap();
+                let vtable = meta.unwrap_meta();
                 try_validation!(
                     self.ecx.memory.check_ptr_access(
                         vtable,
@@ -276,7 +272,7 @@
             }
             ty::Slice(..) | ty::Str => {
                 let _len = try_validation!(
-                    meta.unwrap().to_machine_usize(self.ecx),
+                    meta.unwrap_meta().to_machine_usize(self.ecx),
                     "non-integer slice length in wide pointer",
                     self.path
                 );
@@ -571,7 +567,7 @@
     ) -> InterpResult<'tcx> {
         match op.layout.ty.kind {
             ty::Str => {
-                let mplace = op.assert_mem_place(); // strings are never immediate
+                let mplace = op.assert_mem_place(self.ecx); // strings are never immediate
                 try_validation!(
                     self.ecx.read_str(mplace),
                     "uninitialized or non-UTF-8 data in str",
@@ -587,34 +583,24 @@
                     // padding.
                     match tys.kind {
                         ty::Int(..) | ty::Uint(..) | ty::Float(..) => true,
-                        ty::Tuple(tys) if tys.len() == 0 => true,
-                        ty::Adt(adt_def, _)
-                            if adt_def.is_struct() && adt_def.all_fields().next().is_none() =>
-                        {
-                            true
-                        }
                         _ => false,
                     }
                 } =>
             {
                 // Optimized handling for arrays of integer/float type.
 
-                // bailing out for zsts is ok, since the array element type can only be int/float
-                if op.layout.is_zst() {
-                    return Ok(());
-                }
-                // non-ZST array cannot be immediate, slices are never immediate
-                let mplace = op.assert_mem_place();
+                // Arrays cannot be immediate, slices are never immediate.
+                let mplace = op.assert_mem_place(self.ecx);
                 // This is the length of the array/slice.
                 let len = mplace.len(self.ecx)?;
-                // zero length slices have nothing to be checked
+                // Zero length slices have nothing to be checked.
                 if len == 0 {
                     return Ok(());
                 }
                 // This is the element type size.
-                let ty_size = self.ecx.layout_of(tys)?.size;
+                let layout = self.ecx.layout_of(tys)?;
                 // This is the size in bytes of the whole array.
-                let size = ty_size * len;
+                let size = layout.size * len;
                 // Size is not 0, get a pointer.
                 let ptr = self.ecx.force_ptr(mplace.ptr)?;
 
@@ -644,7 +630,7 @@
                                 // Some byte was undefined, determine which
                                 // element that byte belongs to so we can
                                 // provide an index.
-                                let i = (offset.bytes() / ty_size.bytes()) as usize;
+                                let i = (offset.bytes() / layout.size.bytes()) as usize;
                                 self.path.push(PathElem::ArrayElem(i));
 
                                 throw_validation_failure!("undefined bytes", self.path)
@@ -655,6 +641,13 @@
                     }
                 }
             }
+            // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element
+            // of an array and not all of them, because there's only a single value of a specific
+            // ZST type, so either validation fails for all elements or none.
+            ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(tys)?.is_zst() => {
+                // Validate just the first element
+                self.walk_aggregate(op, fields.take(1))?
+            }
             _ => {
                 self.walk_aggregate(op, fields)? // default handler
             }
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index 2cfcf0f..d2594e8 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -223,7 +223,7 @@
                 match v.layout().ty.kind {
                     ty::Dynamic(..) => {
                         // immediate trait objects are not a thing
-                        let dest = v.to_op(self.ecx())?.assert_mem_place();
+                        let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
                         let inner = self.ecx().unpack_dyn_trait(dest)?.1;
                         trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                         // recurse with the inner type
@@ -292,13 +292,7 @@
                     },
                     layout::FieldPlacement::Array { .. } => {
                         // Let's get an mplace first.
-                        let mplace = if v.layout().is_zst() {
-                            // it's a ZST, the memory content cannot matter
-                            MPlaceTy::dangling(v.layout(), self.ecx())
-                        } else {
-                            // non-ZST array/slice/str cannot be immediate
-                            v.to_op(self.ecx())?.assert_mem_place()
-                        };
+                        let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
                         // Now we can go over all the fields.
                         let iter = self.ecx().mplace_array_fields(mplace)?
                             .map(|f| f.and_then(|f| {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 32b35c4..5e42ba3 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -7,13 +7,12 @@
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
 #![feature(inner_deref)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
 #![feature(core_intrinsics)]
-#![feature(const_fn)]
 #![feature(decl_macro)]
 #![feature(drain_filter)]
 #![feature(exhaustive_patterns)]
@@ -35,16 +34,11 @@
 extern crate log;
 #[macro_use]
 extern crate rustc;
-#[macro_use]
-extern crate syntax;
 
 mod borrow_check;
-mod build;
 pub mod const_eval;
 pub mod dataflow;
-mod hair;
 pub mod interpret;
-mod lints;
 pub mod monomorphize;
 mod shim;
 pub mod transform;
@@ -54,15 +48,19 @@
 
 pub fn provide(providers: &mut Providers<'_>) {
     borrow_check::provide(providers);
+    const_eval::provide(providers);
     shim::provide(providers);
     transform::provide(providers);
     monomorphize::partitioning::provide(providers);
     providers.const_eval_validated = const_eval::const_eval_validated_provider;
     providers.const_eval_raw = const_eval::const_eval_raw_provider;
-    providers.check_match = hair::pattern::check_match;
     providers.const_caller_location = const_eval::const_caller_location;
     providers.const_field = |tcx, param_env_and_value| {
         let (param_env, (value, field)) = param_env_and_value.into_parts();
         const_eval::const_field(tcx, param_env, None, field, value)
     };
+    providers.destructure_const = |tcx, param_env_and_value| {
+        let (param_env, value) = param_env_and_value.into_parts();
+        const_eval::destructure_const(tcx, param_env, value)
+    };
 }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 0943be9..dd2071a 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -182,11 +182,11 @@
 use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::mir::visit::Visitor as MirVisitor;
-use rustc::mir::{self, Location, PlaceBase, Static, StaticKind};
+use rustc::mir::{self, Local, Location};
 use rustc::session::config::EntryFnType;
 use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc::ty::print::obsolete::DefPathBasedNames;
-use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
@@ -194,7 +194,7 @@
 use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_index::bit_set::GrowableBitSet;
-
+use smallvec::SmallVec;
 use std::iter;
 
 #[derive(PartialEq)]
@@ -227,12 +227,7 @@
         }
     }
 
-    fn record_accesses<I>(&mut self, source: MonoItem<'tcx>, new_targets: I)
-    where
-        I: Iterator<Item = (MonoItem<'tcx>, bool)> + ExactSizeIterator,
-    {
-        assert!(!self.index.contains_key(&source));
-
+    fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: &[(MonoItem<'tcx>, bool)]) {
         let start_index = self.targets.len();
         let new_items_count = new_targets.len();
         let new_items_count_total = new_items_count + self.targets.len();
@@ -240,15 +235,15 @@
         self.targets.reserve(new_items_count);
         self.inlines.ensure(new_items_count_total);
 
-        for (i, (target, inline)) in new_targets.enumerate() {
-            self.targets.push(target);
-            if inline {
+        for (i, (target, inline)) in new_targets.iter().enumerate() {
+            self.targets.push(*target);
+            if *inline {
                 self.inlines.insert(i + start_index);
             }
         }
 
         let end_index = self.targets.len();
-        self.index.insert(source, (start_index, end_index));
+        assert!(self.index.insert(source, (start_index, end_index)).is_none());
     }
 
     // Internally iterate over all items referenced by `source` which will be
@@ -283,10 +278,8 @@
 ) -> (FxHashSet<MonoItem<'_>>, InliningMap<'_>) {
     let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
 
-    let roots = tcx.sess.time("collecting roots", || {
-        let _prof_timer = tcx.prof.generic_activity("monomorphization_collector_root_collections");
-        collect_roots(tcx, mode)
-    });
+    let roots =
+        tcx.sess.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode));
 
     debug!("building mono item graph, beginning at roots");
 
@@ -297,7 +290,7 @@
         let visited: MTRef<'_, _> = &mut visited;
         let inlining_map: MTRef<'_, _> = &mut inlining_map;
 
-        tcx.sess.time("collecting mono items", || {
+        tcx.sess.time("monomorphization_collector_graph_walk", || {
             par_iter(roots).for_each(|root| {
                 let mut recursion_depths = DefIdMap::default();
                 collect_items_rec(tcx, root, visited, &mut recursion_depths, inlining_map);
@@ -405,10 +398,15 @@
         mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
     };
 
-    let accesses =
-        callees.into_iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)));
+    // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
+    // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
+    // instead to avoid creating this `SmallVec`.
+    let accesses: SmallVec<[_; 128]> = callees
+        .into_iter()
+        .map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)))
+        .collect();
 
-    inlining_map.lock_mut().record_accesses(caller, accesses);
+    inlining_map.lock_mut().record_accesses(caller, &accesses);
 }
 
 fn check_recursion_limit<'tcx>(
@@ -420,7 +418,7 @@
     let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
     debug!(" => recursion depth={}", recursion_depth);
 
-    let recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+    let adjusted_recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
         // HACK: drop_in_place creates tight monomorphization loops. Give
         // it more margin.
         recursion_depth / 4
@@ -431,7 +429,7 @@
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
-    if recursion_depth > *tcx.sess.recursion_limit.get() {
+    if adjusted_recursion_depth > *tcx.sess.recursion_limit.get() {
         let error = format!("reached the recursion limit while instantiating `{}`", instance);
         if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
             tcx.sess.span_fatal(tcx.hir().span(hir_id), &error);
@@ -644,39 +642,10 @@
 
     fn visit_place_base(
         &mut self,
-        place_base: &mir::PlaceBase<'tcx>,
+        _place_local: &Local,
         _context: mir::visit::PlaceContext,
-        location: Location,
+        _location: Location,
     ) {
-        match place_base {
-            PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => {
-                debug!("visiting static {:?} @ {:?}", def_id, location);
-
-                let tcx = self.tcx;
-                let instance = Instance::mono(tcx, *def_id);
-                if should_monomorphize_locally(tcx, &instance) {
-                    self.output.push(MonoItem::Static(*def_id));
-                }
-            }
-            PlaceBase::Static(box Static {
-                kind: StaticKind::Promoted(promoted, substs),
-                def_id,
-                ..
-            }) => {
-                let instance = Instance::new(*def_id, substs.subst(self.tcx, self.param_substs));
-                match self.tcx.const_eval_promoted(instance, *promoted) {
-                    Ok(val) => collect_const(self.tcx, val, substs, self.output),
-                    Err(ErrorHandled::Reported) => {}
-                    Err(ErrorHandled::TooGeneric) => {
-                        let span = self.tcx.promoted_mir(*def_id)[*promoted].span;
-                        span_bug!(span, "collection encountered polymorphic constant")
-                    }
-                }
-            }
-            PlaceBase::Local(_) => {
-                // Locals have no relevance for collector.
-            }
-        }
     }
 }
 
@@ -744,7 +713,8 @@
 // need a mono item.
 fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
     let def_id = match instance.def {
-        ty::InstanceDef::Item(def_id) => def_id,
+        ty::InstanceDef::Item(def_id) | ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+
         ty::InstanceDef::VtableShim(..)
         | ty::InstanceDef::ReifyShim(..)
         | ty::InstanceDef::ClosureOnceShim { .. }
@@ -756,18 +726,18 @@
     };
 
     if tcx.is_foreign_item(def_id) {
-        // We can always link to foreign items.
+        // Foreign items are always linked against, there's no way of
+        // instantiating them.
         return false;
     }
 
     if def_id.is_local() {
-        // Local items cannot be referred to locally without monomorphizing them locally.
+        // Local items cannot be referred to locally without
+        // monomorphizing them locally.
         return true;
     }
 
-    if tcx.is_reachable_non_generic(def_id)
-        || is_available_upstream_generic(tcx, def_id, instance.substs)
-    {
+    if tcx.is_reachable_non_generic(def_id) || instance.upstream_monomorphization(tcx).is_some() {
         // We can link to the item in question, no instance needed
         // in this crate.
         return false;
@@ -776,35 +746,8 @@
     if !tcx.is_mir_available(def_id) {
         bug!("cannot create local mono-item for {:?}", def_id)
     }
+
     return true;
-
-    fn is_available_upstream_generic<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> bool {
-        debug_assert!(!def_id.is_local());
-
-        // If we are not in share generics mode, we don't link to upstream
-        // monomorphizations but always instantiate our own internal versions
-        // instead.
-        if !tcx.sess.opts.share_generics() {
-            return false;
-        }
-
-        // If this instance has non-erasable parameters, it cannot be a shared
-        // monomorphization. Non-generic instances are already handled above
-        // by `is_reachable_non_generic()`.
-        if substs.non_erasable_generics().next().is_none() {
-            return false;
-        }
-
-        // Take a look at the available monomorphizations listed in the metadata
-        // of upstream crates.
-        tcx.upstream_monomorphizations_for(def_id)
-            .map(|set| set.contains_key(substs))
-            .unwrap_or(false)
-    }
 }
 
 /// For a given pair of source and target type that occur in an unsizing coercion,
@@ -985,7 +928,7 @@
                 // Nothing to do, just keep recursing.
             }
 
-            hir::ItemKind::Impl(..) => {
+            hir::ItemKind::Impl { .. } => {
                 if self.mode == MonoItemCollectionMode::Eager {
                     create_mono_items_for_default_impls(self.tcx, item, self.output);
                 }
@@ -1129,7 +1072,7 @@
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
     match item.kind {
-        hir::ItemKind::Impl(_, _, _, ref generics, .., ref impl_item_refs) => {
+        hir::ItemKind::Impl { ref generics, ref items, .. } => {
             for param in generics.params {
                 match param.kind {
                     hir::GenericParamKind::Lifetime { .. } => {}
@@ -1150,7 +1093,7 @@
                 let param_env = ty::ParamEnv::reveal_all();
                 let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
                 let overridden_methods: FxHashSet<_> =
-                    impl_item_refs.iter().map(|iiref| iiref.ident.modern()).collect();
+                    items.iter().map(|iiref| iiref.ident.modern()).collect();
                 for method in tcx.provided_trait_methods(trait_ref.def_id) {
                     if overridden_methods.contains(&method.ident.modern()) {
                         continue;
@@ -1251,8 +1194,8 @@
                 collect_miri(tcx, id, output);
             }
         }
-        ty::ConstKind::Unevaluated(def_id, substs) => {
-            match tcx.const_eval_resolve(param_env, def_id, substs, None) {
+        ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
+            match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
                 Ok(val) => collect_const(tcx, val, param_substs, output),
                 Err(ErrorHandled::Reported) => {}
                 Err(ErrorHandled::TooGeneric) => {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index c004417..8bcf420 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -104,6 +104,7 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{self, DefIdTree, InstanceDef, TyCtxt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::sync;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_span::symbol::Symbol;
@@ -323,7 +324,7 @@
     };
 
     let def_id = match instance.def {
-        InstanceDef::Item(def_id) => def_id,
+        InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
 
         // These are all compiler glue and such, never exported, always hidden.
         InstanceDef::VtableShim(..)
@@ -796,6 +797,8 @@
     I: Iterator<Item = &'a MonoItem<'tcx>>,
     'tcx: 'a,
 {
+    let _prof_timer = tcx.prof.generic_activity("assert_symbols_are_distinct");
+
     let mut symbols: Vec<_> =
         mono_items.map(|mono_item| (mono_item, mono_item.symbol_name(tcx))).collect();
 
@@ -865,25 +868,26 @@
         }
     };
 
-    let (items, inlining_map) = tcx.sess.time("monomorphization collection", || {
-        collector::collect_crate_mono_items(tcx, collection_mode)
-    });
+    let (items, inlining_map) = collector::collect_crate_mono_items(tcx, collection_mode);
 
     tcx.sess.abort_if_errors();
 
-    assert_symbols_are_distinct(tcx, items.iter());
+    let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
+        sync::join(
+            || {
+                let strategy = if tcx.sess.opts.incremental.is_some() {
+                    PartitioningStrategy::PerModule
+                } else {
+                    PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
+                };
 
-    let strategy = if tcx.sess.opts.incremental.is_some() {
-        PartitioningStrategy::PerModule
-    } else {
-        PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
-    };
-
-    let codegen_units = tcx.sess.time("codegen unit partitioning", || {
-        partition(tcx, items.iter().cloned(), strategy, &inlining_map)
-            .into_iter()
-            .map(Arc::new)
-            .collect::<Vec<_>>()
+                partition(tcx, items.iter().cloned(), strategy, &inlining_map)
+                    .into_iter()
+                    .map(Arc::new)
+                    .collect::<Vec<_>>()
+            },
+            || assert_symbols_are_distinct(tcx, items.iter()),
+        )
     });
 
     let mono_items: DefIdSet = items
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 01cecdd..b846161 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -31,9 +31,13 @@
 
     let mut result = match instance {
         ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance),
-        ty::InstanceDef::VtableShim(def_id) => {
-            build_call_shim(tcx, instance, Adjustment::DerefMove, CallKind::Direct(def_id), None)
-        }
+        ty::InstanceDef::VtableShim(def_id) => build_call_shim(
+            tcx,
+            instance,
+            Some(Adjustment::DerefMove),
+            CallKind::Direct(def_id),
+            None,
+        ),
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
             let trait_ = tcx.trait_of_item(def_id).unwrap();
             let adjustment = match tcx.lang_items().fn_trait_kind(trait_) {
@@ -50,7 +54,7 @@
             let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
             let arg_tys = sig.inputs();
 
-            build_call_shim(tcx, instance, adjustment, CallKind::Indirect, Some(arg_tys))
+            build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect, Some(arg_tys))
         }
         // We are generating a call back to our def-id, which the
         // codegen backend knows to turn to an actual call, be it
@@ -58,7 +62,7 @@
         // indirect calls must be codegen'd differently than direct ones
         // (such as `#[track_caller]`).
         ty::InstanceDef::ReifyShim(def_id) => {
-            build_call_shim(tcx, instance, Adjustment::Identity, CallKind::Direct(def_id), None)
+            build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None)
         }
         ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
             let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
@@ -68,7 +72,13 @@
                 .unwrap()
                 .def_id;
 
-            build_call_shim(tcx, instance, Adjustment::RefMut, CallKind::Direct(call_mut), None)
+            build_call_shim(
+                tcx,
+                instance,
+                Some(Adjustment::RefMut),
+                CallKind::Direct(call_mut),
+                None,
+            )
         }
         ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
         ty::InstanceDef::CloneShim(def_id, ty) => {
@@ -648,7 +658,7 @@
 fn build_call_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
-    rcvr_adjustment: Adjustment,
+    rcvr_adjustment: Option<Adjustment>,
     call_kind: CallKind,
     untuple_args: Option<&[Ty<'tcx>]>,
 ) -> BodyAndCache<'tcx> {
@@ -680,14 +690,16 @@
     let mut local_decls = local_decls_for_sig(&sig, span);
     let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
 
-    let rcvr_arg = Local::new(1 + 0);
-    let rcvr_l = Place::from(rcvr_arg);
+    let rcvr_place = || {
+        assert!(rcvr_adjustment.is_some());
+        Place::from(Local::new(1 + 0))
+    };
     let mut statements = vec![];
 
-    let rcvr = match rcvr_adjustment {
-        Adjustment::Identity => Operand::Move(rcvr_l),
-        Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)),
-        Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_l)),
+    let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
+        Adjustment::Identity => Operand::Move(rcvr_place()),
+        Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_place())),
+        Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())),
         Adjustment::RefMut => {
             // let rcvr = &mut rcvr;
             let ref_rcvr = local_decls.push(temp_decl(
@@ -703,15 +715,15 @@
                 source_info,
                 kind: StatementKind::Assign(box (
                     Place::from(ref_rcvr),
-                    Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l),
+                    Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
                 )),
             });
             Operand::Move(Place::from(ref_rcvr))
         }
-    };
+    });
 
     let (callee, mut args) = match call_kind {
-        CallKind::Indirect => (rcvr, vec![]),
+        CallKind::Indirect => (rcvr.unwrap(), vec![]),
         CallKind::Direct(def_id) => {
             let ty = tcx.type_of(def_id);
             (
@@ -720,21 +732,35 @@
                     user_ty: None,
                     literal: ty::Const::zero_sized(tcx, ty),
                 }),
-                vec![rcvr],
+                rcvr.into_iter().collect::<Vec<_>>(),
             )
         }
     };
 
-    if let Some(untuple_args) = untuple_args {
-        args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
-            let arg_place = Place::from(Local::new(1 + 1));
-            Operand::Move(tcx.mk_place_field(arg_place, Field::new(i), *ity))
-        }));
-    } else {
-        args.extend((1..sig.inputs().len()).map(|i| Operand::Move(Place::from(Local::new(1 + i)))));
+    let mut arg_range = 0..sig.inputs().len();
+
+    // Take the `self` ("receiver") argument out of the range (it's adjusted above).
+    if rcvr_adjustment.is_some() {
+        arg_range.start += 1;
     }
 
-    let n_blocks = if let Adjustment::RefMut = rcvr_adjustment { 5 } else { 2 };
+    // Take the last argument, if we need to untuple it (handled below).
+    if untuple_args.is_some() {
+        arg_range.end -= 1;
+    }
+
+    // Pass all of the non-special arguments directly.
+    args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::new(1 + i)))));
+
+    // Untuple the last argument, if we have to.
+    if let Some(untuple_args) = untuple_args {
+        let tuple_arg = Local::new(1 + (sig.inputs().len() - 1));
+        args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
+            Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), Field::new(i), *ity))
+        }));
+    }
+
+    let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
     let mut blocks = IndexVec::with_capacity(n_blocks);
     let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
         blocks.push(BasicBlockData {
@@ -752,7 +778,7 @@
             func: callee,
             args,
             destination: Some((Place::return_place(), BasicBlock::new(1))),
-            cleanup: if let Adjustment::RefMut = rcvr_adjustment {
+            cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
                 Some(BasicBlock::new(3))
             } else {
                 None
@@ -762,13 +788,13 @@
         false,
     );
 
-    if let Adjustment::RefMut = rcvr_adjustment {
+    if let Some(Adjustment::RefMut) = rcvr_adjustment {
         // BB #1 - drop for Self
         block(
             &mut blocks,
             vec![],
             TerminatorKind::Drop {
-                location: Place::from(rcvr_arg),
+                location: rcvr_place(),
                 target: BasicBlock::new(2),
                 unwind: None,
             },
@@ -777,13 +803,13 @@
     }
     // BB #1/#2 - return
     block(&mut blocks, vec![], TerminatorKind::Return, false);
-    if let Adjustment::RefMut = rcvr_adjustment {
+    if let Some(Adjustment::RefMut) = rcvr_adjustment {
         // BB #3 - drop if closure panics
         block(
             &mut blocks,
             vec![],
             TerminatorKind::Drop {
-                location: Place::from(rcvr_arg),
+                location: rcvr_place(),
                 target: BasicBlock::new(4),
                 unwind: None,
             },
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index 1583647..3263905 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,16 +1,15 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
 use rustc::session::config::nightly_options;
+use rustc::session::parse::feature_err;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use syntax::feature_gate::feature_err;
 
 use super::{ConstKind, Item};
 
-use rustc_error_codes::*;
-
 /// An operation that is not *always* allowed in a const context.
 pub trait NonConstOp: std::fmt::Debug {
     /// Whether this operation can be evaluated by miri.
@@ -115,12 +114,7 @@
             &format!("`{}` is not yet stable as a const fn", item.tcx.def_path_str(def_id)),
         );
         if nightly_options::is_nightly_build() {
-            help!(
-                &mut err,
-                "add `#![feature({})]` to the \
-                   crate attributes to enable",
-                feature
-            );
+            err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
         }
         err.emit();
     }
@@ -197,13 +191,14 @@
 pub struct CellBorrow;
 impl NonConstOp for CellBorrow {
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        span_err!(
+        struct_span_err!(
             item.tcx.sess,
             span,
             E0492,
             "cannot borrow a constant which may contain \
             interior mutability, create a static instead"
-        );
+        )
+        .emit();
     }
 }
 
@@ -353,16 +348,18 @@
             item.tcx.sess,
             span,
             E0013,
-            "{}s cannot refer to statics, use \
-                                        a constant instead",
+            "{}s cannot refer to statics",
             item.const_kind()
         );
+        err.help(
+            "consider extracting the value of the `static` to a `const`, and referring to that",
+        );
         if item.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
-                "Static and const variables can refer to other const variables. \
-                    But a const variable cannot refer to a static variable.",
+                "`static` and `const` variables can refer to other `const` variables. \
+                    A `const` variable, however, cannot refer to a `static` variable.",
             );
-            err.help("To fix this, the value can be extracted as a const and then used.");
+            err.help("To fix this, the value can be extracted to a `const` and then used.");
         }
         err.emit();
     }
@@ -375,13 +372,14 @@
     const IS_SUPPORTED_IN_MIRI: bool = false;
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        span_err!(
+        struct_span_err!(
             item.tcx.sess,
             span,
             E0625,
             "thread-local statics cannot be \
             accessed at compile-time"
-        );
+        )
+        .emit();
     }
 }
 
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 0799cc2..577736f 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -38,12 +38,15 @@
         place: PlaceRef<'_, 'tcx>,
     ) -> bool {
         if let [proj_base @ .., elem] = place.projection {
-            let base_qualif =
-                Self::in_place(cx, per_local, PlaceRef { base: place.base, projection: proj_base });
+            let base_qualif = Self::in_place(
+                cx,
+                per_local,
+                PlaceRef { local: place.local, projection: proj_base },
+            );
             let qualif = base_qualif
                 && Self::in_any_value_of_ty(
                     cx,
-                    Place::ty_from(place.base, proj_base, *cx.body, cx.tcx)
+                    Place::ty_from(place.local, proj_base, *cx.body, cx.tcx)
                         .projection_ty(cx.tcx, elem)
                         .ty,
                 );
@@ -75,11 +78,8 @@
         place: PlaceRef<'_, 'tcx>,
     ) -> bool {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => per_local(*local),
-            PlaceRef { base: PlaceBase::Static(_), projection: [] } => {
-                bug!("qualifying already promoted MIR")
-            }
-            PlaceRef { base: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
+            PlaceRef { local, projection: [] } => per_local(*local),
+            PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
         }
     }
 
@@ -102,7 +102,9 @@
                     // Note: this uses `constant.literal.ty` which is a reference or pointer to the
                     // type of the actual `static` item.
                     Self::in_any_value_of_ty(cx, constant.literal.ty)
-                } else if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
+                } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val
+                {
+                    assert!(promoted.is_none());
                     // Don't peek inside trait associated constants.
                     if cx.tcx.trait_of_item(def_id).is_some() {
                         Self::in_any_value_of_ty(cx, constant.literal.ty)
@@ -147,12 +149,12 @@
             Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
                 // Special-case reborrows to be more like a copy of the reference.
                 if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
                         return Self::in_place(
                             cx,
                             per_local,
-                            PlaceRef { base: &place.base, projection: proj_base },
+                            PlaceRef { local: &place.local, projection: proj_base },
                         );
                     }
                 }
diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs
index 2076830..2cd2495 100644
--- a/src/librustc_mir/transform/check_consts/resolver.rs
+++ b/src/librustc_mir/transform/check_consts/resolver.rs
@@ -47,15 +47,15 @@
         debug_assert!(!place.is_indirect());
 
         match (value, place.as_ref()) {
-            (true, mir::PlaceRef { base: &mir::PlaceBase::Local(local), .. }) => {
-                self.qualifs_per_local.insert(local);
+            (true, mir::PlaceRef { local, .. }) => {
+                self.qualifs_per_local.insert(*local);
             }
 
             // For now, we do not clear the qualif if a local is overwritten in full by
             // an unqualified rvalue (e.g. `y = 5`). This is to be consistent
             // with aggregates where we overwrite all fields with assignments, which would not
             // get this feature.
-            (false, mir::PlaceRef { base: &mir::PlaceBase::Local(_local), projection: &[] }) => {
+            (false, mir::PlaceRef { local: _, projection: &[] }) => {
                 // self.qualifs_per_local.remove(*local);
             }
 
@@ -158,7 +158,7 @@
     const BOTTOM_VALUE: bool = false;
 }
 
-impl<Q> dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+impl<Q> dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
 where
     Q: Qualif,
 {
@@ -173,7 +173,12 @@
     fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
         self.transfer_function(state).initialize_state();
     }
+}
 
+impl<Q> dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+where
+    Q: Qualif,
+{
     fn apply_statement_effect(
         &self,
         state: &mut BitSet<Self::Idx>,
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 3c52a2e..44b2a90 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -6,7 +6,7 @@
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::cast::CastTy;
 use rustc::ty::{self, TyCtxt};
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir::{def_id::DefId, HirId};
 use rustc_index::bit_set::BitSet;
 use rustc_span::symbol::sym;
@@ -20,6 +20,7 @@
 use super::qualifs::{self, HasMutInterior, NeedsDrop};
 use super::resolver::FlowSensitiveAnalysis;
 use super::{is_lang_panic_fn, ConstKind, Item, Qualif};
+use crate::const_eval::{is_const_fn, is_unstable_const_fn};
 use crate::dataflow::{self as old_dataflow, generic as dataflow};
 
 pub type IndirectlyMutableResults<'mir, 'tcx> =
@@ -31,11 +32,10 @@
 }
 
 impl<Q: Qualif> QualifCursor<'a, 'mir, 'tcx, Q> {
-    pub fn new(q: Q, item: &'a Item<'mir, 'tcx>, dead_unwinds: &BitSet<BasicBlock>) -> Self {
+    pub fn new(q: Q, item: &'a Item<'mir, 'tcx>) -> Self {
         let analysis = FlowSensitiveAnalysis::new(q, item);
-        let results =
-            dataflow::Engine::new(item.tcx, &item.body, item.def_id, dead_unwinds, analysis)
-                .iterate_to_fixpoint();
+        let results = dataflow::Engine::new_generic(item.tcx, &item.body, item.def_id, analysis)
+            .iterate_to_fixpoint();
         let cursor = dataflow::ResultsCursor::new(*item.body, results);
 
         let mut in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len());
@@ -144,12 +144,10 @@
 
 impl Validator<'a, 'mir, 'tcx> {
     pub fn new(item: &'a Item<'mir, 'tcx>) -> Self {
+        let needs_drop = QualifCursor::new(NeedsDrop, item);
+        let has_mut_interior = QualifCursor::new(HasMutInterior, item);
+
         let dead_unwinds = BitSet::new_empty(item.body.basic_blocks().len());
-
-        let needs_drop = QualifCursor::new(NeedsDrop, item, &dead_unwinds);
-
-        let has_mut_interior = QualifCursor::new(HasMutInterior, item, &dead_unwinds);
-
         let indirectly_mutable = old_dataflow::do_dataflow(
             item.tcx,
             &*item.body,
@@ -172,7 +170,7 @@
         let Item { tcx, body, def_id, const_kind, .. } = *self.item;
 
         let use_min_const_fn_checks = (const_kind == Some(ConstKind::ConstFn)
-            && tcx.is_min_const_fn(def_id))
+            && crate::const_eval::is_min_const_fn(tcx, def_id))
             && !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
 
         if use_min_const_fn_checks {
@@ -302,8 +300,8 @@
                             PlaceContext::MutatingUse(MutatingUseContext::Borrow)
                         }
                     };
-                    self.visit_place_base(&place.base, ctx, location);
-                    self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+                    self.visit_place_base(&place.local, ctx, location);
+                    self.visit_projection(&place.local, reborrowed_proj, ctx, location);
                     return;
                 }
             }
@@ -315,8 +313,8 @@
                         }
                         Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
                     };
-                    self.visit_place_base(&place.base, ctx, location);
-                    self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+                    self.visit_place_base(&place.local, ctx, location);
+                    self.visit_projection(&place.local, reborrowed_proj, ctx, location);
                     return;
                 }
             }
@@ -367,15 +365,6 @@
 
             Rvalue::AddressOf(Mutability::Mut, _) => self.check_op(ops::MutAddressOf),
 
-            // At the moment, `PlaceBase::Static` is only used for promoted MIR.
-            Rvalue::Ref(_, BorrowKind::Shared, ref place)
-            | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
-            | Rvalue::AddressOf(Mutability::Not, ref place)
-                if matches!(place.base, PlaceBase::Static(_)) =>
-            {
-                bug!("Saw a promoted during const-checking, which must run before promotion")
-            }
-
             Rvalue::Ref(_, BorrowKind::Shared, ref place)
             | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => {
                 self.check_immutable_borrow_like(location, place)
@@ -419,26 +408,14 @@
         }
     }
 
-    fn visit_place_base(
-        &mut self,
-        place_base: &PlaceBase<'tcx>,
-        context: PlaceContext,
-        location: Location,
-    ) {
+    fn visit_place_base(&mut self, place_local: &Local, context: PlaceContext, location: Location) {
         trace!(
-            "visit_place_base: place_base={:?} context={:?} location={:?}",
-            place_base,
+            "visit_place_base: place_local={:?} context={:?} location={:?}",
+            place_local,
             context,
             location,
         );
-        self.super_place_base(place_base, context, location);
-
-        match place_base {
-            PlaceBase::Local(_) => {}
-            PlaceBase::Static(_) => {
-                bug!("Promotion must be run after const validation");
-            }
-        }
+        self.super_place_base(place_local, context, location);
     }
 
     fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
@@ -451,30 +428,30 @@
     }
     fn visit_projection_elem(
         &mut self,
-        place_base: &PlaceBase<'tcx>,
+        place_local: &Local,
         proj_base: &[PlaceElem<'tcx>],
         elem: &PlaceElem<'tcx>,
         context: PlaceContext,
         location: Location,
     ) {
         trace!(
-            "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
+            "visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
             context={:?} location={:?}",
-            place_base,
+            place_local,
             proj_base,
             elem,
             context,
             location,
         );
 
-        self.super_projection_elem(place_base, proj_base, elem, context, location);
+        self.super_projection_elem(place_local, proj_base, elem, context, location);
 
         match elem {
             ProjectionElem::Deref => {
-                let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
+                let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
                 if let ty::RawPtr(_) = base_ty.kind {
                     if proj_base.is_empty() {
-                        if let (PlaceBase::Local(local), []) = (place_base, proj_base) {
+                        if let (local, []) = (place_local, proj_base) {
                             let decl = &self.body.local_decls[*local];
                             if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
                                 let span = decl.source_info.span;
@@ -495,7 +472,7 @@
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {
-                let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
+                let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
                 match base_ty.ty_adt_def() {
                     Some(def) if def.is_union() => {
                         self.check_op(ops::UnionAccess);
@@ -559,13 +536,13 @@
                 };
 
                 // At this point, we are calling a function whose `DefId` is known...
-                if self.tcx.is_const_fn(def_id) {
+                if is_const_fn(self.tcx, def_id) {
                     return;
                 }
 
                 if is_lang_panic_fn(self.tcx, def_id) {
                     self.check_op(ops::Panic);
-                } else if let Some(feature) = self.tcx.is_unstable_const_fn(def_id) {
+                } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
                     // Exempt unstable const fns inside of macros with
                     // `#[allow_internal_unstable]`.
                     if !self.span.allows_unstable(feature) {
@@ -679,17 +656,15 @@
 
         // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
         // that points to the allocation for the static. Don't treat these as reborrows.
-        if let PlaceBase::Local(local) = place.base {
-            if body.local_decls[local].is_ref_to_static() {
-                return None;
-            }
+        if body.local_decls[place.local].is_ref_to_static() {
+            return None;
         }
 
         // Ensure the type being derefed is a reference and not a raw pointer.
         //
         // This is sufficient to prevent an access to a `static mut` from being marked as a
         // reborrow, even if the check above were to disappear.
-        let inner_ty = Place::ty_from(&place.base, inner, body, tcx).ty;
+        let inner_ty = Place::ty_from(&place.local, inner, body, tcx).ty;
         match inner_ty.kind {
             ty::Ref(..) => Some(inner),
             _ => None,
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index b333bc6..59d370a 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -1,4 +1,4 @@
-use rustc::hir::intravisit;
+use rustc::hir::map::Map;
 use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc::mir::*;
@@ -6,17 +6,18 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit;
 use rustc_hir::Node;
 use rustc_span::symbol::{sym, Symbol};
 
 use std::ops::Bound;
 
+use crate::const_eval::{is_const_fn, is_min_const_fn};
 use crate::util;
 
-use rustc_error_codes::*;
-
 pub struct UnsafetyChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     const_context: bool,
@@ -187,18 +188,6 @@
     }
 
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
-        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, .. }) => {
-                bug!("StaticKind::Static should not exist");
-            }
-        }
-
         for (i, elem) in place.projection.iter().enumerate() {
             let proj_base = &place.projection[..i];
 
@@ -226,7 +215,7 @@
                 }
             }
             let is_borrow_of_interior_mut = context.is_borrow()
-                && !Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty.is_freeze(
+                && !Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty.is_freeze(
                     self.tcx,
                     self.param_env,
                     self.source_info.span,
@@ -241,35 +230,37 @@
                 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 let (local, []) = (&place.local, proj_base) {
                 let decl = &self.body.local_decls[*local];
                 if decl.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;
-                } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
-                    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,
-                        );
-                        return;
-                    } else if self.tcx.is_foreign_item(def_id) {
-                        self.require_unsafe(
-                            "use of extern static",
-                            "extern statics are not controlled by the Rust type system: \
-                        invalid data, aliasing violations or data races will cause \
-                        undefined behavior",
-                            UnsafetyViolationKind::General,
-                        );
-                        return;
+                    if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
+                        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,
+                            );
+                            return;
+                        } else if self.tcx.is_foreign_item(def_id) {
+                            self.require_unsafe(
+                                "use of extern static",
+                                "extern statics are not controlled by the Rust type system: \
+                            invalid data, aliasing violations or data races will cause \
+                            undefined behavior",
+                                UnsafetyViolationKind::General,
+                            );
+                            return;
+                        }
+                    } else {
+                        // 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;
+            let base_ty = Place::ty_from(&place.local, proj_base, self.body, self.tcx).ty;
             match base_ty.kind {
                 ty::RawPtr(..) => self.require_unsafe(
                     "dereference of raw pointer",
@@ -423,7 +414,8 @@
             match elem {
                 ProjectionElem::Field(..) => {
                     let ty =
-                        Place::ty_from(&place.base, proj_base, &self.body.local_decls, self.tcx).ty;
+                        Place::ty_from(&place.local, proj_base, &self.body.local_decls, self.tcx)
+                            .ty;
                     match ty.kind {
                         ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
                             (Bound::Unbounded, Bound::Unbounded) => {}
@@ -474,7 +466,9 @@
 }
 
 impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
         intravisit::NestedVisitorMap::None
     }
 
@@ -522,7 +516,7 @@
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
         hir::BodyOwnerKind::Closure => (false, false),
-        hir::BodyOwnerKind::Fn => (tcx.is_const_fn(def_id), tcx.is_min_const_fn(def_id)),
+        hir::BodyOwnerKind::Fn => (is_const_fn(tcx, def_id), is_min_const_fn(tcx, def_id)),
         hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false),
     };
     let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env);
@@ -643,17 +637,17 @@
                 if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) {
                     tcx.unsafe_derive_on_repr_packed(impl_def_id);
                 } else {
-                    tcx.lint_node_note(
+                    tcx.struct_span_lint_hir(
                         SAFE_PACKED_BORROWS,
                         lint_hir_id,
                         source_info.span,
                         &format!(
-                            "{} is unsafe and requires unsafe function or block \
-                                            (error E0133)",
+                            "{} is unsafe and requires unsafe function or block (error E0133)",
                             description
                         ),
-                        &details.as_str(),
-                    );
+                    )
+                    .note(&details.as_str())
+                    .emit();
                 }
             }
         }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 6b0f7be..d645f6c 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -10,15 +10,16 @@
 };
 use rustc::mir::{
     read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant,
-    Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, ReadOnlyBodyAndCache, Rvalue,
+    Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue,
     SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
     UnOp, RETURN_PLACE,
 };
+use rustc::traits;
 use rustc::ty::layout::{
     HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout,
 };
-use rustc::ty::subst::InternalSubsts;
-use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
@@ -29,11 +30,10 @@
 
 use crate::const_eval::error_to_const_error;
 use crate::interpret::{
-    self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx,
-    LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
-    ScalarMaybeUndef, StackPopCleanup,
+    self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InternKind,
+    InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy,
+    Pointer, ScalarMaybeUndef, StackPopCleanup,
 };
-use crate::rustc::ty::subst::Subst;
 use crate::transform::{MirPass, MirSource};
 
 /// The maximum number of bytes that we'll allocate space for a return value.
@@ -75,6 +75,46 @@
             return;
         }
 
+        // Check if it's even possible to satisfy the 'where' clauses
+        // for this item.
+        // This branch will never be taken for any normal function.
+        // However, it's possible to `#!feature(trivial_bounds)]` to write
+        // a function with impossible to satisfy clauses, e.g.:
+        // `fn foo() where String: Copy {}`
+        //
+        // We don't usually need to worry about this kind of case,
+        // since we would get a compilation error if the user tried
+        // to call it. However, since we can do const propagation
+        // even without any calls to the function, we need to make
+        // sure that it even makes sense to try to evaluate the body.
+        // If there are unsatisfiable where clauses, then all bets are
+        // off, and we just give up.
+        //
+        // We manually filter the predicates, skipping anything that's not
+        // "global". We are in a potentially generic context
+        // (e.g. we are evaluating a function without substituting generic
+        // parameters, so this filtering serves two purposes:
+        //
+        // 1. We skip evaluating any predicates that we would
+        // never be able prove are unsatisfiable (e.g. `<T as Foo>`
+        // 2. We avoid trying to normalize predicates involving generic
+        // parameters (e.g. `<T as Foo>::MyItem`). This can confuse
+        // the normalization code (leading to cycle errors), since
+        // it's usually never invoked in this way.
+        let predicates = tcx
+            .predicates_of(source.def_id())
+            .predicates
+            .iter()
+            .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None })
+            .collect();
+        if !traits::normalize_and_test_predicates(
+            tcx,
+            traits::elaborate_predicates(tcx, predicates).collect(),
+        ) {
+            trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", source.def_id());
+            return;
+        }
+
         trace!("ConstProp starting for {:?}", source.def_id());
 
         let dummy_body = &Body::new(
@@ -248,8 +288,6 @@
     }
 }
 
-type Const<'tcx> = OpTy<'tcx>;
-
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
@@ -347,7 +385,7 @@
         }
     }
 
-    fn get_const(&self, local: Local) -> Option<Const<'tcx>> {
+    fn get_const(&self, local: Local) -> Option<OpTy<'tcx>> {
         if local == RETURN_PLACE {
             // Try to read the return place as an immediate so that if it is representable as a
             // scalar, we can handle it as such, but otherwise, just return the value as is.
@@ -426,18 +464,27 @@
         r
     }
 
-    fn eval_constant(
-        &mut self,
-        c: &Constant<'tcx>,
-        source_info: SourceInfo,
-    ) -> Option<Const<'tcx>> {
+    fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         self.ecx.tcx.span = c.span;
+
+        // FIXME we need to revisit this for #67176
+        if c.needs_subst() {
+            return None;
+        }
+
         match self.ecx.eval_const_to_op(c.literal, None) {
             Ok(op) => Some(op),
             Err(error) => {
                 let err = error_to_const_error(&self.ecx, error);
-                match self.lint_root(source_info) {
-                    Some(lint_root) if c.literal.needs_subst() => {
+                if let Some(lint_root) = self.lint_root(source_info) {
+                    let lint_only = match c.literal.val {
+                        // Promoteds must lint and not error as the user didn't ask for them
+                        ConstKind::Unevaluated(_, _, Some(_)) => true,
+                        // Out of backwards compatibility we cannot report hard errors in unused
+                        // generic functions using associated constants of the generic parameters.
+                        _ => c.literal.needs_subst(),
+                    };
+                    if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
                         // generic functions using associated constants of the generic parameters.
                         err.report_as_lint(
@@ -446,22 +493,23 @@
                             lint_root,
                             Some(c.span),
                         );
-                    }
-                    _ => {
+                    } else {
                         err.report_as_error(self.ecx.tcx, "erroneous constant used");
                     }
+                } else {
+                    err.report_as_error(self.ecx.tcx, "erroneous constant used");
                 }
                 None
             }
         }
     }
 
-    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
+    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         trace!("eval_place(place={:?})", place);
         self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None))
     }
 
-    fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
+    fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         match *op {
             Operand::Constant(ref c) => self.eval_constant(c, source_info),
             Operand::Move(ref place) | Operand::Copy(ref place) => {
@@ -552,6 +600,11 @@
             return None;
         }
 
+        // FIXME we need to revisit this for #67176
+        if rvalue.needs_subst() {
+            return None;
+        }
+
         let overflow_check = self.tcx.sess.overflow_checks();
 
         // Perform any special handling for specific Rvalue types.
@@ -577,28 +630,11 @@
                 self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?;
             }
 
-            // Work around: avoid ICE in miri. FIXME(wesleywiser)
-            // The Miri engine ICEs when taking a reference to an uninitialized unsized
-            // local. There's nothing it can do here: taking a reference needs an allocation
-            // which needs to know the size. Normally that's okay as during execution
-            // (e.g. for CTFE) it can never happen. But here in const_prop
-            // unknown data is uninitialized, so if e.g. a function argument is unsized
-            // and has a reference taken, we get an ICE.
+            // Do not try creating references (#67862)
             Rvalue::Ref(_, _, place_ref) => {
-                trace!("checking Ref({:?})", place_ref);
+                trace!("skipping Ref({:?})", place_ref);
 
-                if let Some(local) = place_ref.as_local() {
-                    let alive = if let LocalValue::Live(_) = self.ecx.frame().locals[local].value {
-                        true
-                    } else {
-                        false
-                    };
-
-                    if !alive {
-                        trace!("skipping Ref({:?}) to uninitialized local", place);
-                        return None;
-                    }
-                }
+                return None;
             }
 
             _ => {}
@@ -622,7 +658,7 @@
     fn replace_with_const(
         &mut self,
         rval: &mut Rvalue<'tcx>,
-        value: Const<'tcx>,
+        value: OpTy<'tcx>,
         source_info: SourceInfo,
     ) {
         trace!("attepting to replace {:?} with {:?}", rval, value);
@@ -707,7 +743,8 @@
                 ScalarMaybeUndef::Scalar(r),
             )) => l.is_bits() && r.is_bits(),
             interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
-                intern_const_alloc_recursive(&mut self.ecx, None, op.assert_mem_place())
+                let mplace = op.assert_mem_place(&self.ecx);
+                intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false)
                     .expect("failed to intern alloc");
                 true
             }
@@ -865,9 +902,7 @@
                         // doesn't use the invalid value
                         match cond {
                             Operand::Move(ref place) | Operand::Copy(ref place) => {
-                                if let PlaceBase::Local(local) = place.base {
-                                    self.remove_const(local);
-                                }
+                                self.remove_const(place.local);
                             }
                             Operand::Constant(_) => {}
                         }
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 86baf4d..b9d9ed5 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -28,7 +28,13 @@
         let param_env = tcx.param_env(src.def_id()).with_reveal_all();
         let move_data = match MoveData::gather_moves(body, tcx, param_env) {
             Ok(move_data) => move_data,
-            Err(_) => bug!("No `move_errors` should be allowed in MIR borrowck"),
+            Err((move_data, _)) => {
+                tcx.sess.delay_span_bug(
+                    body.span,
+                    "No `move_errors` should be allowed in MIR borrowck",
+                );
+                move_data
+            }
         };
         let elaborate_patch = {
             let body = &*body;
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 96fb992..8ac7772 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -112,17 +112,17 @@
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.base == PlaceBase::Local(self_arg()) {
+        if place.local == self_arg() {
             replace_base(
                 place,
                 Place {
-                    base: PlaceBase::Local(self_arg()),
-                    projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
+                    local: self_arg(),
+                    projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]),
                 },
                 self.tcx,
             );
         } else {
-            self.visit_place_base(&mut place.base, context, location);
+            self.visit_place_base(&mut place.local, context, location);
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
@@ -148,12 +148,12 @@
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.base == PlaceBase::Local(self_arg()) {
+        if place.local == self_arg() {
             replace_base(
                 place,
                 Place {
-                    base: PlaceBase::Local(self_arg()),
-                    projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Field(
+                    local: self_arg(),
+                    projection: self.tcx().intern_place_elems(&[ProjectionElem::Field(
                         Field::new(0),
                         self.ref_gen_ty,
                     )]),
@@ -161,7 +161,7 @@
                 self.tcx,
             );
         } else {
-            self.visit_place_base(&mut place.base, context, location);
+            self.visit_place_base(&mut place.local, context, location);
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
@@ -173,7 +173,7 @@
 }
 
 fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
-    place.base = new_base.base;
+    place.local = new_base.local;
 
     let mut new_projection = new_base.projection.to_vec();
     new_projection.append(&mut place.projection.to_vec());
@@ -236,7 +236,7 @@
         let mut projection = base.projection.to_vec();
         projection.push(ProjectionElem::Field(Field::new(idx), ty));
 
-        Place { base: base.base, projection: self.tcx.intern_place_elems(&projection) }
+        Place { local: base.local, projection: self.tcx.intern_place_elems(&projection) }
     }
 
     // Create a statement which changes the discriminant
@@ -275,20 +275,15 @@
         assert_eq!(self.remap.get(local), None);
     }
 
-    fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if let PlaceBase::Local(l) = place.base {
-            // Replace an Local in the remap with a generator struct access
-            if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) {
-                replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
-            }
-        } else {
-            self.visit_place_base(&mut place.base, context, location);
-
-            for elem in place.projection.iter() {
-                if let PlaceElem::Index(local) = elem {
-                    assert_ne!(*local, self_arg());
-                }
-            }
+    fn visit_place(
+        &mut self,
+        place: &mut Place<'tcx>,
+        _context: PlaceContext,
+        _location: Location,
+    ) {
+        // Replace an Local in the remap with a generator struct access
+        if let Some(&(ty, variant_index, idx)) = self.remap.get(&place.local) {
+            replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
         }
     }
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 3c5d2c9..2dd00fe 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -430,12 +430,7 @@
                         }
                     }
 
-                    match place.base {
-                        // Static variables need a borrow because the callee
-                        // might modify the same static.
-                        PlaceBase::Static(_) => true,
-                        _ => false,
-                    }
+                    false
                 }
 
                 let dest = if dest_needs_borrow(&destination.0) {
@@ -647,10 +642,7 @@
 
     fn make_integrate_local(&self, local: &Local) -> Local {
         if *local == RETURN_PLACE {
-            match self.destination.base {
-                PlaceBase::Local(l) => return l,
-                PlaceBase::Static(ref s) => bug!("Return place is {:?}, not local", s),
-            }
+            return self.destination.local;
         }
 
         let idx = local.index() - 1;
@@ -672,19 +664,14 @@
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        match &mut place.base {
-            PlaceBase::Static(_) => {}
-            PlaceBase::Local(l) => {
-                // If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
-                let dest_proj_len = self.destination.projection.len();
-                if *l == RETURN_PLACE && dest_proj_len > 0 {
-                    let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
-                    projs.extend(self.destination.projection);
-                    projs.extend(place.projection);
+        // If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
+        let dest_proj_len = self.destination.projection.len();
+        if place.local == RETURN_PLACE && dest_proj_len > 0 {
+            let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
+            projs.extend(self.destination.projection);
+            projs.extend(place.projection);
 
-                    place.projection = self.tcx.intern_place_elems(&*projs);
-                }
-            }
+            place.projection = self.tcx.intern_place_elems(&*projs);
         }
         // Handles integrating any locals that occur in the base
         // or projections
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index a2f3fce..afe42e6 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -3,7 +3,7 @@
 use crate::transform::{MirPass, MirSource};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::mir::{
-    read_only, Body, BodyAndCache, Constant, Local, Location, Operand, Place, PlaceBase, PlaceRef,
+    read_only, Body, BodyAndCache, Constant, Local, Location, Operand, Place, PlaceRef,
     ProjectionElem, Rvalue,
 };
 use rustc::ty::{self, TyCtxt};
@@ -51,11 +51,11 @@
             let new_place = match rvalue {
                 Rvalue::Ref(_, _, place) => {
                     if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() {
-                        place.projection = self.tcx().intern_place_elems(&vec![proj_r.clone()]);
+                        place.projection = self.tcx().intern_place_elems(&[proj_r.clone()]);
 
                         Place {
                             // Replace with dummy
-                            base: mem::replace(&mut place.base, PlaceBase::Local(Local::new(0))),
+                            local: mem::replace(&mut place.local, Local::new(0)),
                             projection: self.tcx().intern_place_elems(proj_l),
                         }
                     } else {
@@ -92,10 +92,10 @@
 impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         if let Rvalue::Ref(_, _, place) = rvalue {
-            if let PlaceRef { base, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
+            if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
                 place.as_ref()
             {
-                if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
+                if Place::ty_from(local, proj_base, self.body, self.tcx).ty.is_region_ptr() {
                     self.optimizations.and_stars.insert(location);
                 }
             }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 82c31a0..3c37ecc 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,11 +1,12 @@
-use crate::{build, shim};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use crate::{shim, util};
+use rustc::hir::map::Map;
 use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted};
 use rustc::ty::query::Providers;
 use rustc::ty::steal::Steal;
 use rustc::ty::{InstanceDef, TyCtxt, TypeFoldable};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::IndexVec;
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -35,12 +36,12 @@
 pub mod simplify_branches;
 pub mod simplify_try;
 pub mod uninhabited_enum_branching;
+pub mod unreachable_prop;
 
 pub(crate) fn provide(providers: &mut Providers<'_>) {
     self::check_unsafety::provide(providers);
     *providers = Providers {
         mir_keys,
-        mir_built,
         mir_const,
         mir_const_qualif,
         mir_validated,
@@ -85,7 +86,8 @@
             }
             intravisit::walk_struct_def(self, v)
         }
-        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
+        type Map = Map<'tcx>;
+        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, Self::Map> {
             NestedVisitorMap::None
         }
     }
@@ -96,11 +98,6 @@
     tcx.arena.alloc(set)
 }
 
-fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
-    let mir = build::mir_build(tcx, def_id);
-    tcx.alloc_steal_mir(mir)
-}
-
 /// Where a specific `mir::Body` comes from.
 #[derive(Debug, Copy, Clone)]
 pub struct MirSource<'tcx> {
@@ -220,6 +217,9 @@
     let _ = tcx.unsafety_check_result(def_id);
 
     let mut body = tcx.mir_built(def_id).steal();
+
+    util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
+
     run_passes(
         tcx,
         &mut body,
@@ -300,6 +300,7 @@
             // From here on out, regions are gone.
             &erase_regions::EraseRegions,
             // Optimizations begin.
+            &unreachable_prop::UnreachablePropagation,
             &uninhabited_enum_branching::UninhabitedEnumBranching,
             &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
             &inline::Inline,
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index b6656e7..f058ac8 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -27,8 +27,9 @@
 use rustc_target::spec::abi::Abi;
 
 use std::cell::Cell;
-use std::{iter, mem, usize};
+use std::{cmp, iter, mem, usize};
 
+use crate::const_eval::{is_const_fn, is_unstable_const_fn};
 use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstKind, Item};
 use crate::transform::{MirPass, MirSource};
 
@@ -38,7 +39,7 @@
 /// errors when promotion of `#[rustc_args_required_const]` arguments fails.
 ///
 /// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
-/// newly created `StaticKind::Promoted`.
+/// newly created `Constant`.
 #[derive(Default)]
 pub struct PromoteTemps<'tcx> {
     pub promoted_fragments: Cell<IndexVec<Promoted, BodyAndCache<'tcx>>>,
@@ -307,18 +308,14 @@
 
                         // We can only promote interior borrows of promotable temps (non-temps
                         // don't get promoted anyway).
-                        let base = match place.base {
-                            PlaceBase::Local(local) => local,
-                            _ => return Err(Unpromotable),
-                        };
-                        self.validate_local(base)?;
+                        self.validate_local(place.local)?;
 
                         if place.projection.contains(&ProjectionElem::Deref) {
                             return Err(Unpromotable);
                         }
 
                         let mut has_mut_interior =
-                            self.qualif_local::<qualifs::HasMutInterior>(base);
+                            self.qualif_local::<qualifs::HasMutInterior>(place.local);
                         // HACK(eddyb) this should compute the same thing as
                         // `<HasMutInterior as Qualif>::in_projection` from
                         // `check_consts::qualifs` but without recursion.
@@ -332,7 +329,7 @@
                                 // FIXME(eddyb) this is probably excessive, with
                                 // the exception of `union` member accesses.
                                 let ty =
-                                    Place::ty_from(&place.base, proj_base, *self.body, self.tcx)
+                                    Place::ty_from(&place.local, proj_base, *self.body, self.tcx)
                                         .projection_ty(self.tcx, elem)
                                         .ty;
                                 if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@@ -348,7 +345,7 @@
                         if has_mut_interior {
                             return Err(Unpromotable);
                         }
-                        if self.qualif_local::<qualifs::NeedsDrop>(base) {
+                        if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
                             return Err(Unpromotable);
                         }
 
@@ -478,13 +475,8 @@
 
     fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> {
         match place {
-            PlaceRef { base: PlaceBase::Local(local), projection: [] } => {
-                self.validate_local(*local)
-            }
-            PlaceRef { base: PlaceBase::Static(_), projection: [] } => {
-                bug!("qualifying already promoted MIR")
-            }
-            PlaceRef { base: _, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local, projection: [] } => self.validate_local(*local),
+            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
                 match *elem {
                     ProjectionElem::Deref | ProjectionElem::Downcast(..) => {
                         return Err(Unpromotable);
@@ -499,7 +491,7 @@
                     ProjectionElem::Field(..) => {
                         if self.const_kind.is_none() {
                             let base_ty =
-                                Place::ty_from(place.base, proj_base, *self.body, self.tcx).ty;
+                                Place::ty_from(place.local, proj_base, *self.body, self.tcx).ty;
                             if let Some(def) = base_ty.ty_adt_def() {
                                 // No promotion of union field accesses.
                                 if def.is_union() {
@@ -510,7 +502,7 @@
                     }
                 }
 
-                self.validate_place(PlaceRef { base: place.base, projection: proj_base })
+                self.validate_place(PlaceRef { local: place.local, projection: proj_base })
             }
         }
     }
@@ -597,10 +589,12 @@
                 // Raw reborrows can come from reference to pointer coercions,
                 // so are allowed.
                 if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
-                        return self
-                            .validate_place(PlaceRef { base: &place.base, projection: proj_base });
+                        return self.validate_place(PlaceRef {
+                            local: &place.local,
+                            projection: proj_base,
+                        });
                     }
                 }
                 Err(Unpromotable)
@@ -634,9 +628,9 @@
                 // Special-case reborrows to be more like a copy of the reference.
                 let mut place = place.as_ref();
                 if let [proj_base @ .., ProjectionElem::Deref] = &place.projection {
-                    let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty;
+                    let base_ty = Place::ty_from(&place.local, proj_base, *self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
-                        place = PlaceRef { base: &place.base, projection: proj_base };
+                        place = PlaceRef { local: &place.local, projection: proj_base };
                     }
                 }
 
@@ -645,17 +639,15 @@
                 // HACK(eddyb) this should compute the same thing as
                 // `<HasMutInterior as Qualif>::in_projection` from
                 // `check_consts::qualifs` but without recursion.
-                let mut has_mut_interior = match place.base {
-                    PlaceBase::Local(local) => self.qualif_local::<qualifs::HasMutInterior>(*local),
-                    PlaceBase::Static(_) => false,
-                };
+                let mut has_mut_interior =
+                    self.qualif_local::<qualifs::HasMutInterior>(*place.local);
                 if has_mut_interior {
                     let mut place_projection = place.projection;
                     // FIXME(eddyb) use a forward loop instead of a reverse one.
                     while let [proj_base @ .., elem] = place_projection {
                         // FIXME(eddyb) this is probably excessive, with
                         // the exception of `union` member accesses.
-                        let ty = Place::ty_from(place.base, proj_base, *self.body, self.tcx)
+                        let ty = Place::ty_from(place.local, proj_base, *self.body, self.tcx)
                             .projection_ty(self.tcx, elem)
                             .ty;
                         if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
@@ -702,8 +694,8 @@
 
         let is_const_fn = match fn_ty.kind {
             ty::FnDef(def_id, _) => {
-                self.tcx.is_const_fn(def_id)
-                    || self.tcx.is_unstable_const_fn(def_id).is_some()
+                is_const_fn(self.tcx, def_id)
+                    || is_unstable_const_fn(self.tcx, def_id).is_some()
                     || is_lang_panic_fn(self.tcx, self.def_id)
             }
             _ => false,
@@ -760,6 +752,7 @@
     source: &'a mut BodyAndCache<'tcx>,
     promoted: BodyAndCache<'tcx>,
     temps: &'a mut IndexVec<Local, TempState>,
+    extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>,
 
     /// If true, all nested temps are also kept in the
     /// source MIR, not moved to the promoted MIR.
@@ -902,39 +895,76 @@
         candidate: Candidate,
         next_promoted_id: usize,
     ) -> Option<BodyAndCache<'tcx>> {
-        let mut operand = {
+        let mut rvalue = {
             let promoted = &mut self.promoted;
             let promoted_id = Promoted::new(next_promoted_id);
             let tcx = self.tcx;
-            let mut promoted_place = |ty, span| {
+            let mut promoted_operand = |ty, span| {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
-                Place {
-                    base: PlaceBase::Static(box Static {
-                        kind: StaticKind::Promoted(
-                            promoted_id,
-                            InternalSubsts::identity_for_item(tcx, def_id),
-                        ),
+
+                Operand::Constant(Box::new(Constant {
+                    span,
+                    user_ty: None,
+                    literal: tcx.mk_const(ty::Const {
                         ty,
-                        def_id,
+                        val: ty::ConstKind::Unevaluated(
+                            def_id,
+                            InternalSubsts::identity_for_item(tcx, def_id),
+                            Some(promoted_id),
+                        ),
                     }),
-                    projection: List::empty(),
-                }
+                }))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
             match candidate {
                 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 region, borrow_kind, ref mut place),
+                        )) => {
                             // Use the underlying local for this (necessarily interior) borrow.
-                            let ty = place.base.ty(local_decls).ty;
+                            let ty = local_decls.local_decls()[place.local].ty;
                             let span = statement.source_info.span;
 
-                            Operand::Move(Place {
-                                base: mem::replace(&mut place.base, promoted_place(ty, span).base),
-                                projection: List::empty(),
-                            })
+                            let ref_ty = tcx.mk_ref(
+                                tcx.lifetimes.re_erased,
+                                ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
+                            );
+
+                            *region = tcx.lifetimes.re_erased;
+
+                            let mut projection = vec![PlaceElem::Deref];
+                            projection.extend(place.projection);
+                            place.projection = tcx.intern_place_elems(&projection);
+
+                            // Create a temp to hold the promoted reference.
+                            // This is because `*r` requires `r` to be a local,
+                            // otherwise we would use the `promoted` directly.
+                            let mut promoted_ref = LocalDecl::new_temp(ref_ty, span);
+                            promoted_ref.source_info = statement.source_info;
+                            let promoted_ref = local_decls.push(promoted_ref);
+                            assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);
+
+                            let promoted_ref_statement = Statement {
+                                source_info: statement.source_info,
+                                kind: StatementKind::Assign(Box::new((
+                                    Place::from(promoted_ref),
+                                    Rvalue::Use(promoted_operand(ref_ty, span)),
+                                ))),
+                            };
+                            self.extra_statements.push((loc, promoted_ref_statement));
+
+                            Rvalue::Ref(
+                                tcx.lifetimes.re_erased,
+                                borrow_kind,
+                                Place {
+                                    local: mem::replace(&mut place.local, promoted_ref),
+                                    projection: List::empty(),
+                                },
+                            )
                         }
                         _ => bug!(),
                     }
@@ -945,7 +975,8 @@
                         StatementKind::Assign(box (_, Rvalue::Repeat(ref mut operand, _))) => {
                             let ty = operand.ty(local_decls, self.tcx);
                             let span = statement.source_info.span;
-                            mem::replace(operand, Operand::Copy(promoted_place(ty, span)))
+
+                            Rvalue::Use(mem::replace(operand, promoted_operand(ty, span)))
                         }
                         _ => bug!(),
                     }
@@ -956,8 +987,8 @@
                         TerminatorKind::Call { ref mut args, .. } => {
                             let ty = args[index].ty(local_decls, self.tcx);
                             let span = terminator.source_info.span;
-                            let operand = Operand::Copy(promoted_place(ty, span));
-                            mem::replace(&mut args[index], operand)
+
+                            Rvalue::Use(mem::replace(&mut args[index], promoted_operand(ty, span)))
                         }
                         // We expected a `TerminatorKind::Call` for which we'd like to promote an
                         // argument. `qualify_consts` saw a `TerminatorKind::Call` here, but
@@ -974,13 +1005,13 @@
         };
 
         assert_eq!(self.new_block(), START_BLOCK);
-        self.visit_operand(
-            &mut operand,
+        self.visit_rvalue(
+            &mut rvalue,
             Location { block: BasicBlock::new(0), statement_index: usize::MAX },
         );
 
         let span = self.promoted.span;
-        self.assign(RETURN_PLACE, Rvalue::Use(operand), span);
+        self.assign(RETURN_PLACE, rvalue, span);
         Some(self.promoted)
     }
 }
@@ -1019,6 +1050,7 @@
 
     let mut promotions = IndexVec::new();
 
+    let mut extra_statements = vec![];
     for candidate in candidates.into_iter().rev() {
         match candidate {
             Candidate::Repeat(Location { block, statement_index })
@@ -1042,23 +1074,27 @@
         let initial_locals =
             iter::once(LocalDecl::new_return_place(tcx.types.never, body.span)).collect();
 
+        let mut promoted = Body::new(
+            IndexVec::new(),
+            // FIXME: maybe try to filter this to avoid blowing up
+            // memory usage?
+            body.source_scopes.clone(),
+            initial_locals,
+            IndexVec::new(),
+            0,
+            vec![],
+            body.span,
+            vec![],
+            body.generator_kind,
+        );
+        promoted.ignore_interior_mut_in_const_validation = true;
+
         let promoter = Promoter {
-            promoted: BodyAndCache::new(Body::new(
-                IndexVec::new(),
-                // FIXME: maybe try to filter this to avoid blowing up
-                // memory usage?
-                body.source_scopes.clone(),
-                initial_locals,
-                IndexVec::new(),
-                0,
-                vec![],
-                body.span,
-                vec![],
-                body.generator_kind,
-            )),
+            promoted: BodyAndCache::new(promoted),
             tcx,
             source: body,
             temps: &mut temps,
+            extra_statements: &mut extra_statements,
             keep_original: false,
         };
 
@@ -1068,6 +1104,13 @@
         }
     }
 
+    // Insert each of `extra_statements` before its indicated location, which
+    // has to be done in reverse location order, to not invalidate the rest.
+    extra_statements.sort_by_key(|&(loc, _)| cmp::Reverse(loc));
+    for (loc, statement) in extra_statements {
+        body[loc.block].statements.insert(loc.statement_index, statement);
+    }
+
     // Eliminate assignments to, and drops of promoted temps.
     let promoted = |index: Local| temps[index] == TempState::PromotedOut;
     for block in body.basic_blocks_mut() {
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 9dea44e..b047e53 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -5,7 +5,7 @@
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use std::borrow::Cow;
-use syntax::attr;
+use syntax::{ast, attr};
 
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
 
@@ -27,12 +27,19 @@
                     bug!("closure kind predicate on function: {:#?}", predicate)
                 }
                 Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
-                Predicate::Trait(pred) => {
+                Predicate::Trait(pred, constness) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
                     }
                     match pred.skip_binder().self_ty().kind {
                         ty::Param(ref p) => {
+                            // Allow `T: ?const Trait`
+                            if *constness == ast::Constness::NotConst
+                                && feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
+                            {
+                                continue;
+                            }
+
                             let generics = tcx.generics_of(current);
                             let def = generics.type_param(p, tcx);
                             let span = tcx.def_span(def.def_id);
@@ -261,7 +268,7 @@
             ProjectionElem::Downcast(_symbol, _variant_index) => {}
 
             ProjectionElem::Field(..) => {
-                let base_ty = Place::ty_from(&place.base, &proj_base, body, tcx).ty;
+                let base_ty = Place::ty_from(&place.local, &proj_base, body, tcx).ty;
                 if let Some(def) = base_ty.ty_adt_def() {
                     // No union field accesses in `const fn`
                     if def.is_union() {
@@ -281,8 +288,22 @@
     Ok(())
 }
 
-/// Returns whether `allow_internal_unstable(..., <feature_gate>, ...)` is present.
+/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
 fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
+    // All features require that the corresponding gate be enabled,
+    // even if the function has `#[allow_internal_unstable(the_gate)]`.
+    if !tcx.features().enabled(feature_gate) {
+        return false;
+    }
+
+    // If this crate is not using stability attributes, or this function is not claiming to be a
+    // stable `const fn`, that is all that is required.
+    if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
+        return true;
+    }
+
+    // However, we cannot allow stable `const fn`s to use unstable features without an explicit
+    // opt-in via `allow_internal_unstable`.
     attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic())
         .map_or(false, |mut features| features.any(|name| name == feature_gate))
 }
@@ -295,7 +316,11 @@
 ) -> McfResult {
     let span = terminator.source_info.span;
     match &terminator.kind {
-        TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::Resume => Ok(()),
+        TerminatorKind::FalseEdges { .. }
+        | TerminatorKind::FalseUnwind { .. }
+        | TerminatorKind::Goto { .. }
+        | TerminatorKind::Return
+        | TerminatorKind::Resume => Ok(()),
 
         TerminatorKind::Drop { location, .. } => check_place(tcx, location, span, def_id, body),
         TerminatorKind::DropAndReplace { location, value, .. } => {
@@ -303,13 +328,10 @@
             check_operand(tcx, value, span, def_id, body)
         }
 
-        TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. }
-            if !feature_allowed(tcx, def_id, sym::const_if_match) =>
-        {
+        TerminatorKind::SwitchInt { .. } if !feature_allowed(tcx, def_id, sym::const_if_match) => {
             Err((span, "loops and conditional expressions are not stable in const fn".into()))
         }
 
-        TerminatorKind::FalseEdges { .. } => Ok(()),
         TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
             check_operand(tcx, discr, span, def_id, body)
         }
@@ -327,7 +349,7 @@
         TerminatorKind::Call { func, args, from_hir_call: _, destination: _, cleanup: _ } => {
             let fn_ty = func.ty(body, tcx);
             if let ty::FnDef(def_id, _) = fn_ty.kind {
-                if !tcx.is_min_const_fn(def_id) {
+                if !crate::const_eval::is_min_const_fn(tcx, def_id) {
                     return Err((
                         span,
                         format!(
@@ -353,13 +375,5 @@
         TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
             check_operand(tcx, cond, span, def_id, body)
         }
-
-        TerminatorKind::FalseUnwind { .. } if feature_allowed(tcx, def_id, sym::const_loop) => {
-            Ok(())
-        }
-
-        TerminatorKind::FalseUnwind { .. } => {
-            Err((span, "loops are not allowed in const fn".into()))
-        }
     }
 }
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index fb7f4fa..ddf8d73 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -388,13 +388,7 @@
         // Remove unnecessary StorageLive and StorageDead annotations.
         data.statements.retain(|stmt| match &stmt.kind {
             StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => self.map[*l].is_some(),
-            StatementKind::Assign(box (place, _)) => {
-                if let PlaceBase::Local(local) = place.base {
-                    self.map[local].is_some()
-                } else {
-                    true
-                }
-            }
+            StatementKind::Assign(box (place, _)) => self.map[place.local].is_some(),
             _ => true,
         });
         self.super_basic_block_data(block, data);
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index 3b8871f..e733b0a 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -137,9 +137,9 @@
 fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
     match place.as_ref() {
         PlaceRef {
-            base: &PlaceBase::Local(local),
+            local,
             projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
-        } => Some((local, VarField { field, field_ty: ty, var_idx })),
+        } => Some((*local, VarField { field, field_ty: ty, var_idx })),
         _ => None,
     }
 }
diff --git a/src/librustc_mir/transform/unreachable_prop.rs b/src/librustc_mir/transform/unreachable_prop.rs
new file mode 100644
index 0000000..27173e0
--- /dev/null
+++ b/src/librustc_mir/transform/unreachable_prop.rs
@@ -0,0 +1,108 @@
+//! A pass that propagates the unreachable terminator of a block to its predecessors
+//! when all of their successors are unreachable. This is achieved through a
+//! post-order traversal of the blocks.
+
+use crate::transform::simplify;
+use crate::transform::{MirPass, MirSource};
+use rustc::mir::*;
+use rustc::ty::TyCtxt;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use std::borrow::Cow;
+
+pub struct UnreachablePropagation;
+
+impl MirPass<'_> for UnreachablePropagation {
+    fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
+        if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
+            // Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt
+            // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
+            return;
+        }
+
+        let mut unreachable_blocks = FxHashSet::default();
+        let mut replacements = FxHashMap::default();
+
+        for (bb, bb_data) in traversal::postorder(body) {
+            let terminator = bb_data.terminator();
+            // HACK: If the block contains any asm statement it is not regarded as unreachable.
+            // This is a temporary solution that handles possibly diverging asm statements.
+            // Accompanying testcases: mir-opt/unreachable_asm.rs and mir-opt/unreachable_asm_2.rs
+            let asm_stmt_in_block = || {
+                bb_data.statements.iter().any(|stmt: &Statement<'_>| match stmt.kind {
+                    StatementKind::InlineAsm(..) => true,
+                    _ => false,
+                })
+            };
+
+            if terminator.kind == TerminatorKind::Unreachable && !asm_stmt_in_block() {
+                unreachable_blocks.insert(bb);
+            } else {
+                let is_unreachable = |succ: BasicBlock| unreachable_blocks.contains(&succ);
+                let terminator_kind_opt = remove_successors(&terminator.kind, is_unreachable);
+
+                if let Some(terminator_kind) = terminator_kind_opt {
+                    if terminator_kind == TerminatorKind::Unreachable && !asm_stmt_in_block() {
+                        unreachable_blocks.insert(bb);
+                    }
+                    replacements.insert(bb, terminator_kind);
+                }
+            }
+        }
+
+        let replaced = !replacements.is_empty();
+        for (bb, terminator_kind) in replacements {
+            body.basic_blocks_mut()[bb].terminator_mut().kind = terminator_kind;
+        }
+
+        if replaced {
+            simplify::remove_dead_blocks(body);
+        }
+    }
+}
+
+fn remove_successors<F>(
+    terminator_kind: &TerminatorKind<'tcx>,
+    predicate: F,
+) -> Option<TerminatorKind<'tcx>>
+where
+    F: Fn(BasicBlock) -> bool,
+{
+    match *terminator_kind {
+        TerminatorKind::Goto { target } if predicate(target) => Some(TerminatorKind::Unreachable),
+        TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
+            let original_targets_len = targets.len();
+            let (otherwise, targets) = targets.split_last().unwrap();
+            let retained = values
+                .iter()
+                .zip(targets.iter())
+                .filter(|(_, &t)| !predicate(t))
+                .collect::<Vec<_>>();
+            let mut values = retained.iter().map(|&(v, _)| *v).collect::<Vec<_>>();
+            let mut targets = retained.iter().map(|&(_, d)| *d).collect::<Vec<_>>();
+
+            if !predicate(*otherwise) {
+                targets.push(*otherwise);
+            } else {
+                values.pop();
+            }
+
+            let retained_targets_len = targets.len();
+
+            if targets.is_empty() {
+                Some(TerminatorKind::Unreachable)
+            } else if targets.len() == 1 {
+                Some(TerminatorKind::Goto { target: targets[0] })
+            } else if original_targets_len != retained_targets_len {
+                Some(TerminatorKind::SwitchInt {
+                    discr: discr.clone(),
+                    switch_ty,
+                    values: Cow::from(values),
+                    targets,
+                })
+            } else {
+                None
+            }
+        }
+        _ => None,
+    }
+}
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index 70d6aaf..e17c7a8 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -46,7 +46,7 @@
             // 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.local, proj_base, local_decls, tcx).ty;
                 match ty.kind {
                     ty::Adt(def, _) if def.repr.packed() => return true,
                     _ => {}
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 9f67109..d8ee059 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -1,9 +1,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_errors::{DiagnosticBuilder, DiagnosticId};
+use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
 use rustc_span::{MultiSpan, Span};
 
-use rustc_error_codes::*;
-
 impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
     crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
         struct_span_err!(self, span, E0505, "cannot move out of `{}` because it is borrowed", desc,)
diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml
new file mode 100644
index 0000000..a22c4d1
--- /dev/null
+++ b/src/librustc_mir_build/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_mir_build"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_mir_build"
+path = "lib.rs"
+doctest = false
+
+[dependencies]
+arena = { path = "../libarena" }
+itertools = "0.8"
+log = "0.4"
+rustc = { path = "../librustc" }
+rustc_apfloat = { path = "../librustc_apfloat" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_index = { path = "../librustc_index" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_macros = { path = "../librustc_macros" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
+rustc_target = { path = "../librustc_target" }
+syntax = { path = "../libsyntax" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir_build/build/block.rs
similarity index 99%
rename from src/librustc_mir/build/block.rs
rename to src/librustc_mir_build/build/block.rs
index 2e133a0..c517d31 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir_build/build/block.rs
@@ -7,7 +7,7 @@
 use rustc_span::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn ast_block(
+    crate fn ast_block(
         &mut self,
         destination: &Place<'tcx>,
         block: BasicBlock,
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir_build/build/cfg.rs
similarity index 80%
rename from src/librustc_mir/build/cfg.rs
rename to src/librustc_mir_build/build/cfg.rs
index 553701c..e197110 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir_build/build/cfg.rs
@@ -4,33 +4,33 @@
 use rustc::mir::*;
 
 impl<'tcx> CFG<'tcx> {
-    pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
+    crate fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
         &self.basic_blocks[blk]
     }
 
-    pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
+    crate fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
         &mut self.basic_blocks[blk]
     }
 
     // llvm.org/PR32488 makes this function use an excess of stack space. Mark
     // it as #[inline(never)] to keep rustc's stack use in check.
     #[inline(never)]
-    pub fn start_new_block(&mut self) -> BasicBlock {
+    crate fn start_new_block(&mut self) -> BasicBlock {
         self.basic_blocks.push(BasicBlockData::new(None))
     }
 
-    pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
+    crate fn start_new_cleanup_block(&mut self) -> BasicBlock {
         let bb = self.start_new_block();
         self.block_data_mut(bb).is_cleanup = true;
         bb
     }
 
-    pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
+    crate fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
         debug!("push({:?}, {:?})", block, statement);
         self.block_data_mut(block).statements.push(statement);
     }
 
-    pub fn push_assign(
+    crate fn push_assign(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -43,7 +43,7 @@
         );
     }
 
-    pub fn push_assign_constant(
+    crate fn push_assign_constant(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -53,7 +53,7 @@
         self.push_assign(block, source_info, temp, Rvalue::Use(Operand::Constant(box constant)));
     }
 
-    pub fn push_assign_unit(
+    crate fn push_assign_unit(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -67,7 +67,7 @@
         );
     }
 
-    pub fn push_fake_read(
+    crate fn push_fake_read(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -79,7 +79,7 @@
         self.push(block, stmt);
     }
 
-    pub fn terminate(
+    crate fn terminate(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -96,7 +96,7 @@
     }
 
     /// In the `origin` block, push a `goto -> target` terminator.
-    pub fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
+    crate fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
         self.terminate(origin, source_info, TerminatorKind::Goto { target })
     }
 }
diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir_build/build/expr/as_constant.rs
similarity index 95%
rename from src/librustc_mir/build/expr/as_constant.rs
rename to src/librustc_mir_build/build/expr/as_constant.rs
index ceac2a0..e485626 100644
--- a/src/librustc_mir/build/expr/as_constant.rs
+++ b/src/librustc_mir_build/build/expr/as_constant.rs
@@ -8,7 +8,7 @@
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
     /// `expr` is a valid compile-time constant!
-    pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
+    crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir_build/build/expr/as_operand.rs
similarity index 94%
rename from src/librustc_mir/build/expr/as_operand.rs
rename to src/librustc_mir_build/build/expr/as_operand.rs
index b969932..efe328d 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir_build/build/expr/as_operand.rs
@@ -13,7 +13,7 @@
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
+    crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -27,7 +27,7 @@
     /// this time.
     ///
     /// The operand is known to be live until the end of `scope`.
-    pub fn as_operand<M>(
+    crate fn as_operand<M>(
         &mut self,
         block: BasicBlock,
         scope: Option<region::Scope>,
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs
similarity index 94%
rename from src/librustc_mir/build/expr/as_place.rs
rename to src/librustc_mir_build/build/expr/as_place.rs
index 29eac5e..fd6882f 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir_build/build/expr/as_place.rs
@@ -20,13 +20,13 @@
 /// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
 #[derive(Clone)]
 struct PlaceBuilder<'tcx> {
-    base: PlaceBase<'tcx>,
+    local: Local,
     projection: Vec<PlaceElem<'tcx>>,
 }
 
-impl PlaceBuilder<'tcx> {
+impl<'tcx> PlaceBuilder<'tcx> {
     fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
-        Place { base: self.base, projection: tcx.intern_place_elems(&self.projection) }
+        Place { local: self.local, projection: tcx.intern_place_elems(&self.projection) }
     }
 
     fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
@@ -47,15 +47,9 @@
     }
 }
 
-impl From<Local> for PlaceBuilder<'tcx> {
+impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
     fn from(local: Local) -> Self {
-        Self { base: local.into(), projection: Vec::new() }
-    }
-}
-
-impl From<PlaceBase<'tcx>> for PlaceBuilder<'tcx> {
-    fn from(base: PlaceBase<'tcx>) -> Self {
-        Self { base, projection: Vec::new() }
+        Self { local, projection: Vec::new() }
     }
 }
 
@@ -72,7 +66,7 @@
     /// Extra care is needed if any user code is allowed to run between calling
     /// this method and using it, as is the case for `match` and index
     /// expressions.
-    pub fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
+    crate fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -95,7 +89,11 @@
     /// place. The place itself may or may not be mutable:
     /// * If this expr is a place expr like a.b, then we will return that place.
     /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
-    pub fn as_read_only_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
+    crate fn as_read_only_place<M>(
+        &mut self,
+        mut block: BasicBlock,
+        expr: M,
+    ) -> BlockAnd<Place<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -370,7 +368,7 @@
     ) {
         let tcx = self.hir.tcx();
         let place_ty =
-            Place::ty_from(&base_place.base, &base_place.projection, &self.local_decls, tcx);
+            Place::ty_from(&base_place.local, &base_place.projection, &self.local_decls, tcx);
         if let ty::Slice(_) = place_ty.ty.kind {
             // We need to create fake borrows to ensure that the bounds
             // check that we just did stays valid. Since we can't assign to
@@ -380,7 +378,7 @@
                 match elem {
                     ProjectionElem::Deref => {
                         let fake_borrow_deref_ty = Place::ty_from(
-                            &base_place.base,
+                            &base_place.local,
                             &base_place.projection[..idx],
                             &self.local_decls,
                             tcx,
@@ -398,14 +396,14 @@
                             Rvalue::Ref(
                                 tcx.lifetimes.re_erased,
                                 BorrowKind::Shallow,
-                                Place { base: base_place.base.clone(), projection },
+                                Place { local: base_place.local.clone(), projection },
                             ),
                         );
                         fake_borrow_temps.push(fake_borrow_temp);
                     }
                     ProjectionElem::Index(_) => {
                         let index_ty = Place::ty_from(
-                            &base_place.base,
+                            &base_place.local,
                             &base_place.projection[..idx],
                             &self.local_decls,
                             tcx,
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs
similarity index 96%
rename from src/librustc_mir/build/expr/as_rvalue.rs
rename to src/librustc_mir_build/build/expr/as_rvalue.rs
index 34b0cbf..5959b85 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir_build/build/expr/as_rvalue.rs
@@ -18,7 +18,7 @@
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    pub fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
+    crate fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -276,7 +276,7 @@
         }
     }
 
-    pub fn build_binary_op(
+    crate fn build_binary_op(
         &mut self,
         mut block: BasicBlock,
         op: BinOp,
@@ -393,26 +393,24 @@
         let arg_place = unpack!(block = this.as_place(block, arg));
 
         let mutability = match arg_place.as_ref() {
-            PlaceRef { base: &PlaceBase::Local(local), projection: &[] } => {
-                this.local_decls[local].mutability
-            }
-            PlaceRef { base: &PlaceBase::Local(local), projection: &[ProjectionElem::Deref] } => {
+            PlaceRef { local, projection: &[] } => this.local_decls[*local].mutability,
+            PlaceRef { local, projection: &[ProjectionElem::Deref] } => {
                 debug_assert!(
-                    this.local_decls[local].is_ref_for_guard(),
+                    this.local_decls[*local].is_ref_for_guard(),
                     "Unexpected capture place",
                 );
-                this.local_decls[local].mutability
+                this.local_decls[*local].mutability
             }
             PlaceRef {
-                ref base,
+                ref local,
                 projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             }
             | PlaceRef {
-                ref base,
+                ref local,
                 projection:
                     &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _), ProjectionElem::Deref],
             } => {
-                let place = PlaceRef { base, projection: proj_base };
+                let place = PlaceRef { local, projection: proj_base };
 
                 // Not projected from the implicit `self` in a closure.
                 debug_assert!(
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs
similarity index 98%
rename from src/librustc_mir/build/expr/as_temp.rs
rename to src/librustc_mir_build/build/expr/as_temp.rs
index 3f71104..34dd10c 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir_build/build/expr/as_temp.rs
@@ -11,7 +11,7 @@
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
     /// up rvalues so as to freeze the value that will be consumed.
-    pub fn as_temp<M>(
+    crate fn as_temp<M>(
         &mut self,
         block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
@@ -61,6 +61,7 @@
             }
             if let ExprKind::StaticRef { def_id, .. } = expr.kind {
                 let is_thread_local = this.hir.tcx().has_attr(def_id, sym::thread_local);
+                local_decl.internal = true;
                 local_decl.local_info = LocalInfo::StaticRef { def_id, is_thread_local };
             }
             this.local_decls.push(local_decl)
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir_build/build/expr/category.rs
similarity index 96%
rename from src/librustc_mir/build/expr/category.rs
rename to src/librustc_mir_build/build/expr/category.rs
index b35616c..c4d3409 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir_build/build/expr/category.rs
@@ -1,7 +1,7 @@
 use crate::hair::*;
 
 #[derive(Debug, PartialEq)]
-pub enum Category {
+crate enum Category {
     // An assignable memory location like `x`, `x.f`, `foo()[3]`, that
     // sort of thing. Something that could appear on the LHS of an `=`
     // sign.
@@ -19,7 +19,7 @@
 // Rvalues fall into different "styles" that will determine which fn
 // is best suited to generate them.
 #[derive(Debug, PartialEq)]
-pub enum RvalueFunc {
+crate enum RvalueFunc {
     // Best generated by `into`. This is generally exprs that
     // cause branching, like `match`, but also includes calls.
     Into,
@@ -31,7 +31,7 @@
 /// Determines the category for a given expression. Note that scope
 /// and paren expressions have no category.
 impl Category {
-    pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
+    crate fn of(ek: &ExprKind<'_>) -> Option<Category> {
         match *ek {
             ExprKind::Scope { .. } => None,
 
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
similarity index 99%
rename from src/librustc_mir/build/expr/into.rs
rename to src/librustc_mir_build/build/expr/into.rs
index 2cf2b21..503dfb6 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -14,7 +14,7 @@
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
-    pub fn into_expr(
+    crate fn into_expr(
         &mut self,
         destination: &Place<'tcx>,
         mut block: BasicBlock,
diff --git a/src/librustc_mir/build/expr/mod.rs b/src/librustc_mir_build/build/expr/mod.rs
similarity index 100%
rename from src/librustc_mir/build/expr/mod.rs
rename to src/librustc_mir_build/build/expr/mod.rs
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir_build/build/expr/stmt.rs
similarity index 99%
rename from src/librustc_mir/build/expr/stmt.rs
rename to src/librustc_mir_build/build/expr/stmt.rs
index ff70492..fd61cb8 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir_build/build/expr/stmt.rs
@@ -10,7 +10,7 @@
     /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
     /// span of that statement (including its semicolon, if any).
     /// The scope is used if a statement temporary must be dropped.
-    pub fn stmt_expr(
+    crate fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
         expr: Expr<'tcx>,
diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir_build/build/into.rs
similarity index 90%
rename from src/librustc_mir/build/into.rs
rename to src/librustc_mir_build/build/into.rs
index 9c3ea5f..1a2a9d2 100644
--- a/src/librustc_mir/build/into.rs
+++ b/src/librustc_mir_build/build/into.rs
@@ -18,7 +18,12 @@
 }
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn into<E>(&mut self, destination: &Place<'tcx>, block: BasicBlock, expr: E) -> BlockAnd<()>
+    crate fn into<E>(
+        &mut self,
+        destination: &Place<'tcx>,
+        block: BasicBlock,
+        expr: E,
+    ) -> BlockAnd<()>
     where
         E: EvalInto<'tcx>,
     {
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs
similarity index 98%
rename from src/librustc_mir/build/matches/mod.rs
rename to src/librustc_mir_build/build/matches/mod.rs
index 7eea90b..f9f10b5 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir_build/build/matches/mod.rs
@@ -81,7 +81,7 @@
     ///
     /// * From each prebinding block to the next prebinding block.
     /// * From each otherwise block to the next prebinding block.
-    pub fn match_expr(
+    crate fn match_expr(
         &mut self,
         destination: &Place<'tcx>,
         span: Span,
@@ -417,7 +417,7 @@
         }
     }
 
-    pub fn place_into_pattern(
+    crate fn place_into_pattern(
         &mut self,
         block: BasicBlock,
         irrefutable_pat: Pat<'tcx>,
@@ -488,7 +488,7 @@
     /// scope for the bindings in these patterns, if such a scope had to be
     /// created. NOTE: Declaring the bindings should always be done in their
     /// drop scope.
-    pub fn declare_bindings(
+    crate fn declare_bindings(
         &mut self,
         mut visibility_scope: Option<SourceScope>,
         scope_span: Span,
@@ -525,7 +525,7 @@
         visibility_scope
     }
 
-    pub fn storage_live_binding(
+    crate fn storage_live_binding(
         &mut self,
         block: BasicBlock,
         var: HirId,
@@ -540,7 +540,7 @@
         Place::from(local_id)
     }
 
-    pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
+    crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
         let local_id = self.var_local_id(var, for_guard);
         let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
         self.schedule_drop(span, region_scope, local_id, DropKind::Value);
@@ -641,7 +641,7 @@
 }
 
 #[derive(Debug)]
-pub struct Candidate<'pat, 'tcx> {
+crate struct Candidate<'pat, 'tcx> {
     // span of the original pattern that gave rise to this candidate
     span: Span,
 
@@ -685,7 +685,7 @@
 }
 
 #[derive(Clone, Debug)]
-pub struct MatchPair<'pat, 'tcx> {
+crate struct MatchPair<'pat, 'tcx> {
     // this place...
     place: Place<'tcx>,
 
@@ -739,7 +739,7 @@
 }
 
 #[derive(Debug)]
-pub struct Test<'tcx> {
+crate struct Test<'tcx> {
     span: Span,
     kind: TestKind<'tcx>,
 }
@@ -747,7 +747,7 @@
 /// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
 /// a match arm has a guard expression attached to it.
 #[derive(Copy, Clone, Debug)]
-pub(crate) struct ArmHasGuard(pub bool);
+crate struct ArmHasGuard(crate bool);
 
 ///////////////////////////////////////////////////////////////////////////
 // Main matching algorithm
@@ -890,7 +890,7 @@
                     let proj_base = &source.projection[..i];
 
                     fake_borrows.insert(Place {
-                        base: source.base.clone(),
+                        local: source.local.clone(),
                         projection: self.hir.tcx().intern_place_elems(proj_base),
                     });
                 }
@@ -1241,7 +1241,7 @@
                     // 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: proj_base });
+                    all_fake_borrows.push(PlaceRef { local: &place.local, projection: proj_base });
                 }
             }
 
@@ -1258,7 +1258,7 @@
             .into_iter()
             .map(|matched_place_ref| {
                 let matched_place = Place {
-                    base: matched_place_ref.base.clone(),
+                    local: matched_place_ref.local.clone(),
                     projection: tcx.intern_place_elems(matched_place_ref.projection),
                 };
                 let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
similarity index 98%
rename from src/librustc_mir/build/matches/simplify.rs
rename to src/librustc_mir_build/build/matches/simplify.rs
index 9dbf898..a5f691a 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -24,7 +24,7 @@
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
+    crate fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
             let match_pairs = mem::take(&mut candidate.match_pairs);
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs
similarity index 99%
rename from src/librustc_mir/build/matches/test.rs
rename to src/librustc_mir_build/build/matches/test.rs
index afdb744..31fc0d1 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir_build/build/matches/test.rs
@@ -24,7 +24,7 @@
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
     /// It is a bug to call this with a simplifiable pattern.
-    pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
+    crate fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
         match *match_pair.pattern.kind {
             PatKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
                 span: match_pair.pattern.span,
@@ -85,7 +85,7 @@
         }
     }
 
-    pub fn add_cases_to_switch<'pat>(
+    crate fn add_cases_to_switch<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         candidate: &Candidate<'pat, 'tcx>,
@@ -129,7 +129,7 @@
         }
     }
 
-    pub fn add_variants_to_switch<'pat>(
+    crate fn add_variants_to_switch<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         candidate: &Candidate<'pat, 'tcx>,
@@ -156,7 +156,7 @@
         }
     }
 
-    pub fn perform_test(
+    crate fn perform_test(
         &mut self,
         block: BasicBlock,
         place: &Place<'tcx>,
@@ -507,7 +507,7 @@
     /// that it *doesn't* apply. For now, we return false, indicate that the
     /// test does not apply to this candidate, but it might be we can get
     /// tighter match code if we do something a bit different.
-    pub fn sort_candidate<'pat>(
+    crate fn sort_candidate<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         test: &Test<'tcx>,
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir_build/build/matches/util.rs
similarity index 94%
rename from src/librustc_mir/build/matches/util.rs
rename to src/librustc_mir_build/build/matches/util.rs
index b6e643a6..def8d1b 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir_build/build/matches/util.rs
@@ -8,7 +8,7 @@
 use std::u32;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn field_match_pairs<'pat>(
+    crate fn field_match_pairs<'pat>(
         &mut self,
         place: Place<'tcx>,
         subpatterns: &'pat [FieldPat<'tcx>],
@@ -26,7 +26,7 @@
             .collect()
     }
 
-    pub fn prefix_slice_suffix<'pat>(
+    crate fn prefix_slice_suffix<'pat>(
         &mut self,
         match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
         place: &Place<'tcx>,
@@ -77,7 +77,7 @@
     /// Creates a false edge to `imaginary_target` and a real edge to
     /// real_target. If `imaginary_target` is none, or is the same as the real
     /// target, a Goto is generated instead to simplify the generated MIR.
-    pub fn false_edges(
+    crate fn false_edges(
         &mut self,
         from_block: BasicBlock,
         real_target: BasicBlock,
@@ -98,7 +98,7 @@
 }
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
-    pub fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
+    crate fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
         MatchPair { place, pattern }
     }
 }
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir_build/build/misc.rs
similarity index 81%
rename from src/librustc_mir/build/misc.rs
rename to src/librustc_mir_build/build/misc.rs
index 7c358fe..3d5145b 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir_build/build/misc.rs
@@ -14,7 +14,7 @@
     ///
     /// N.B., **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
-    pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
+    crate fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
         let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
         let place = Place::from(temp);
         debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty);
@@ -23,24 +23,28 @@
 
     /// Convenience function for creating a literal operand, one
     /// without any user type annotation.
-    pub fn literal_operand(&mut self, span: Span, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> {
+    crate fn literal_operand(
+        &mut self,
+        span: Span,
+        literal: &'tcx ty::Const<'tcx>,
+    ) -> Operand<'tcx> {
         let constant = box Constant { span, user_ty: None, literal };
         Operand::Constant(constant)
     }
 
-    pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
+    crate fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
         Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
     }
 
     // Returns a zero literal operand for the appropriate type, works for
     // bool, char and integers.
-    pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
+    crate fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty));
 
         self.literal_operand(span, literal)
     }
 
-    pub fn push_usize(
+    crate fn push_usize(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -61,7 +65,7 @@
         temp
     }
 
-    pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
+    crate fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
         let tcx = self.hir.tcx();
         let ty = place.ty(&self.local_decls, tcx).ty;
         if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir_build/build/mod.rs
similarity index 98%
rename from src/librustc_mir/build/mod.rs
rename to src/librustc_mir_build/build/mod.rs
index d6d22db..44ff493 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -2,8 +2,6 @@
 use crate::build::scope::DropKind;
 use crate::hair::cx::Cx;
 use crate::hair::{BindingMode, LintLevel, PatKind};
-use crate::transform::MirSource;
-use crate::util as mir_util;
 use rustc::middle::lang_items;
 use rustc::middle::region;
 use rustc::mir::*;
@@ -22,8 +20,12 @@
 
 use super::lints;
 
+crate fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::steal::Steal<BodyAndCache<'_>> {
+    tcx.alloc_steal_mir(mir_build(tcx, def_id))
+}
+
 /// Construct the MIR for a given `DefId`.
-pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
+fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
@@ -63,7 +65,7 @@
         } else if cx.body_owner_kind.is_fn_or_closure() {
             // fetch the fully liberated fn signature (that is, all bound
             // types/lifetimes replaced)
-            let fn_sig = cx.tables().liberated_fn_sigs()[id].clone();
+            let fn_sig = cx.tables().liberated_fn_sigs()[id];
             let fn_def_id = tcx.hir().local_def_id(id);
 
             let ty = tcx.type_of(fn_def_id);
@@ -172,8 +174,6 @@
             build::construct_const(cx, body_id, return_ty, return_ty_span)
         };
 
-        mir_util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
-
         lints::check(tcx, &body, def_id);
 
         let mut body = BodyAndCache::new(body);
@@ -202,7 +202,7 @@
 }
 
 #[derive(Debug, PartialEq, Eq)]
-pub enum BlockFrame {
+enum BlockFrame {
     /// Evaluation is currently within a statement.
     ///
     /// Examples include:
@@ -461,7 +461,7 @@
 }
 
 rustc_index::newtype_index! {
-    pub struct ScopeId { .. }
+    struct ScopeId { .. }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -834,7 +834,7 @@
                             span: tcx_hir.span(var_id),
                         },
                         place: Place {
-                            base: closure_env_arg.into(),
+                            local: closure_env_arg.into(),
                             projection: tcx.intern_place_elems(&projs),
                         },
                     });
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir_build/build/scope.rs
similarity index 97%
rename from src/librustc_mir/build/scope.rs
rename to src/librustc_mir_build/build/scope.rs
index 0aa9773..d994b87 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir_build/build/scope.rs
@@ -123,7 +123,7 @@
 }
 
 #[derive(Debug, Default)]
-pub struct Scopes<'tcx> {
+crate struct Scopes<'tcx> {
     scopes: Vec<Scope>,
     /// The current set of breakable scopes. See module comment for more details.
     breakable_scopes: Vec<BreakableScope<'tcx>>,
@@ -183,7 +183,7 @@
 
 /// The target of an expression that breaks out of a scope
 #[derive(Clone, Copy, Debug)]
-pub enum BreakableTarget {
+crate enum BreakableTarget {
     Continue(region::Scope),
     Break(region::Scope),
     Return,
@@ -371,7 +371,7 @@
     // ==========================
     //  Start a breakable scope, which tracks where `continue`, `break` and
     //  `return` should branch to.
-    pub fn in_breakable_scope<F, R>(
+    crate fn in_breakable_scope<F, R>(
         &mut self,
         loop_block: Option<BasicBlock>,
         break_block: BasicBlock,
@@ -395,7 +395,7 @@
         res
     }
 
-    pub fn in_opt_scope<F, R>(
+    crate fn in_opt_scope<F, R>(
         &mut self,
         opt_scope: Option<(region::Scope, SourceInfo)>,
         f: F,
@@ -418,7 +418,7 @@
 
     /// Convenience wrapper that pushes a scope and then executes `f`
     /// to build its contents, popping the scope afterwards.
-    pub fn in_scope<F, R>(
+    crate fn in_scope<F, R>(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
         lint_level: LintLevel,
@@ -463,14 +463,14 @@
     /// scope and call `pop_scope` afterwards. Note that these two
     /// calls must be paired; using `in_scope` as a convenience
     /// wrapper maybe preferable.
-    pub fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
+    crate fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
         self.scopes.push_scope(region_scope, self.source_scope);
     }
 
     /// Pops a scope, which should have region scope `region_scope`,
     /// adding any drops onto the end of `block` that are needed.
     /// This must match 1-to-1 with `push_scope`.
-    pub fn pop_scope(
+    crate fn pop_scope(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
         mut block: BasicBlock,
@@ -500,7 +500,7 @@
         block.unit()
     }
 
-    pub fn break_scope(
+    crate fn break_scope(
         &mut self,
         mut block: BasicBlock,
         value: Option<ExprRef<'tcx>>,
@@ -535,7 +535,7 @@
     /// Branch out of `block` to `target`, exiting all scopes up to
     /// and including `region_scope`. This will insert whatever drops are
     /// needed. See module comment for details.
-    pub fn exit_scope(
+    crate fn exit_scope(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -604,7 +604,7 @@
     ///
     /// This path terminates in GeneratorDrop. Returns the start of the path.
     /// None indicates there’s no cleanup to do at this point.
-    pub fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
+    crate fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
         // Fill in the cache for unwinds
         self.diverge_cleanup_gen(true);
 
@@ -656,7 +656,7 @@
     }
 
     /// Creates a new source scope, nested in the current one.
-    pub fn new_source_scope(
+    crate fn new_source_scope(
         &mut self,
         span: Span,
         lint_level: LintLevel,
@@ -689,7 +689,7 @@
     }
 
     /// Given a span and the current source scope, make a SourceInfo.
-    pub fn source_info(&self, span: Span) -> SourceInfo {
+    crate fn source_info(&self, span: Span) -> SourceInfo {
         SourceInfo { span, scope: self.source_scope }
     }
 
@@ -717,7 +717,7 @@
     ///
     /// When building statics/constants, returns `None` since
     /// intermediate values do not have to be dropped in that case.
-    pub fn local_scope(&self) -> Option<region::Scope> {
+    crate fn local_scope(&self) -> Option<region::Scope> {
         match self.hir.body_owner_kind {
             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) =>
             // No need to free storage in this context.
@@ -729,7 +729,7 @@
     }
 
     // Schedule an abort block - this is used for some ABIs that cannot unwind
-    pub fn schedule_abort(&mut self) -> BasicBlock {
+    crate fn schedule_abort(&mut self) -> BasicBlock {
         let source_info = self.scopes.source_info(self.scopes.len(), self.fn_span);
         let abortblk = self.cfg.start_new_cleanup_block();
         self.cfg.terminate(abortblk, source_info, TerminatorKind::Abort);
@@ -739,7 +739,7 @@
 
     // Scheduling drops
     // ================
-    pub fn schedule_drop_storage_and_value(
+    crate fn schedule_drop_storage_and_value(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -754,7 +754,7 @@
     ///
     /// When called with `DropKind::Storage`, `place` should be a local
     /// with an index higher than the current `self.arg_count`.
-    pub fn schedule_drop(
+    crate fn schedule_drop(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -884,7 +884,7 @@
     /// spurious borrow-check errors -- the problem, ironically, is
     /// not the `DROP(_X)` itself, but the (spurious) unwind pathways
     /// that it creates. See #64391 for an example.
-    pub fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
+    crate fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
         let scope = match self.local_scope() {
             None => {
                 // if there is no local scope, operands won't be dropped anyway
@@ -921,7 +921,7 @@
     ///
     /// This is a special case because the temporary for the condition needs to
     /// be dropped on both the true and the false arm.
-    pub fn test_bool(
+    crate fn test_bool(
         &mut self,
         mut block: BasicBlock,
         condition: Expr<'tcx>,
@@ -978,7 +978,7 @@
     ///
     /// This path terminates in Resume. Returns the start of the path.
     /// See module comment for more details.
-    pub fn diverge_cleanup(&mut self) -> BasicBlock {
+    crate fn diverge_cleanup(&mut self) -> BasicBlock {
         self.diverge_cleanup_gen(false)
     }
 
@@ -1033,7 +1033,7 @@
     }
 
     /// Utility function for *non*-scope code to build their own drops
-    pub fn build_drop_and_replace(
+    crate fn build_drop_and_replace(
         &mut self,
         block: BasicBlock,
         span: Span,
@@ -1059,7 +1059,7 @@
     /// Creates an Assert terminator and return the success block.
     /// If the boolean condition operand is not the expected value,
     /// a runtime panic will be caused with the given message.
-    pub fn assert(
+    crate fn assert(
         &mut self,
         block: BasicBlock,
         cond: Operand<'tcx>,
@@ -1293,7 +1293,7 @@
     target
 }
 
-fn push_storage_deads(
+fn push_storage_deads<'tcx>(
     cfg: &mut CFG<'tcx>,
     target: BasicBlock,
     storage_deads: &mut Vec<Statement<'tcx>>,
diff --git a/src/librustc_mir_build/hair/constant.rs b/src/librustc_mir_build/hair/constant.rs
new file mode 100644
index 0000000..266f473
--- /dev/null
+++ b/src/librustc_mir_build/hair/constant.rs
@@ -0,0 +1,98 @@
+use rustc::mir::interpret::{
+    truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
+};
+use rustc::ty::{self, layout::Size, ParamEnv, TyCtxt};
+use rustc_span::symbol::Symbol;
+use syntax::ast;
+
+crate fn lit_to_const<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    lit_input: LitToConstInput<'tcx>,
+) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
+    let LitToConstInput { lit, ty, neg } = lit_input;
+
+    let trunc = |n| {
+        let param_ty = ParamEnv::reveal_all().and(ty);
+        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
+        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
+        let result = truncate(n, width);
+        trace!("trunc result: {}", result);
+        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
+    };
+
+    let lit = match *lit {
+        ast::LitKind::Str(ref s, _) => {
+            let s = s.as_str();
+            let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
+        }
+        ast::LitKind::ByteStr(ref data) => {
+            if let ty::Ref(_, ref_ty, _) = ty.kind {
+                match ref_ty.kind {
+                    ty::Slice(_) => {
+                        let allocation = Allocation::from_byte_aligned_bytes(data as &Vec<u8>);
+                        let allocation = tcx.intern_const_alloc(allocation);
+                        ConstValue::Slice { data: allocation, start: 0, end: data.len() }
+                    }
+                    ty::Array(_, _) => {
+                        let id = tcx.allocate_bytes(data);
+                        ConstValue::Scalar(Scalar::Ptr(id.into()))
+                    }
+                    _ => {
+                        bug!("bytestring should have type of either &[u8] or &[u8; _], not {}", ty)
+                    }
+                }
+            } else {
+                bug!("bytestring should have type of either &[u8] or &[u8; _], not {}", ty)
+            }
+        }
+        ast::LitKind::Byte(n) => ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))),
+        ast::LitKind::Int(n, _) if neg => {
+            let n = n as i128;
+            let n = n.overflowing_neg().0;
+            trunc(n as u128)?
+        }
+        ast::LitKind::Int(n, _) => trunc(n)?,
+        ast::LitKind::Float(n, _) => {
+            let fty = match ty.kind {
+                ty::Float(fty) => fty,
+                _ => bug!(),
+            };
+            parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
+        }
+        ast::LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
+        ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
+        ast::LitKind::Err(_) => return Err(LitToConstError::Reported),
+    };
+    Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(lit), ty }))
+}
+
+fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result<ConstValue<'tcx>, ()> {
+    let num = num.as_str();
+    use rustc_apfloat::ieee::{Double, Single};
+    let scalar = match fty {
+        ast::FloatTy::F32 => {
+            num.parse::<f32>().map_err(|_| ())?;
+            let mut f = num.parse::<Single>().unwrap_or_else(|e| {
+                panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
+            });
+            if neg {
+                f = -f;
+            }
+            Scalar::from_f32(f)
+        }
+        ast::FloatTy::F64 => {
+            num.parse::<f64>().map_err(|_| ())?;
+            let mut f = num.parse::<Double>().unwrap_or_else(|e| {
+                panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
+            });
+            if neg {
+                f = -f;
+            }
+            Scalar::from_f64(f)
+        }
+    };
+
+    Ok(ConstValue::Scalar(scalar))
+}
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir_build/hair/cx/block.rs
similarity index 98%
rename from src/librustc_mir/hair/cx/block.rs
rename to src/librustc_mir_build/hair/cx/block.rs
index 674c148..a883b84 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir_build/hair/cx/block.rs
@@ -101,7 +101,7 @@
     return result;
 }
 
-pub fn to_expr_ref<'a, 'tcx>(
+crate fn to_expr_ref<'a, 'tcx>(
     cx: &mut Cx<'a, 'tcx>,
     block: &'tcx hir::Block<'tcx>,
 ) -> ExprRef<'tcx> {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
similarity index 98%
rename from src/librustc_mir/hair/cx/expr.rs
rename to src/librustc_mir_build/hair/cx/expr.rs
index 8fd8143..d6786ea 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -411,8 +411,14 @@
             let def_id = cx.tcx.hir().local_def_id(count.hir_id);
             let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
             let span = cx.tcx.def_span(def_id);
-            let count = match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, Some(span)) {
-                Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env),
+            let count = match cx.tcx.const_eval_resolve(
+                ty::ParamEnv::reveal_all(),
+                def_id,
+                substs,
+                None,
+                Some(span),
+            ) {
+                Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()),
                 Err(ErrorHandled::Reported) => 0,
                 Err(ErrorHandled::TooGeneric) => {
                     let span = cx.tcx.def_span(def_id);
@@ -523,7 +529,7 @@
                             // and not the beginning of discriminants (which is always `0`)
                             let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
                             let lhs = mk_const(cx.tcx().mk_const(ty::Const {
-                                val: ty::ConstKind::Unevaluated(did, substs),
+                                val: ty::ConstKind::Unevaluated(did, substs, None),
                                 ty: var_ty,
                             }));
                             let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
@@ -574,8 +580,8 @@
     Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
 }
 
-fn user_substs_applied_to_res(
-    cx: &mut Cx<'a, 'tcx>,
+fn user_substs_applied_to_res<'tcx>(
+    cx: &mut Cx<'_, 'tcx>,
     hir_id: hir::HirId,
     res: Res,
 ) -> Option<ty::CanonicalUserType<'tcx>> {
@@ -719,7 +725,7 @@
             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
             ExprKind::Literal {
                 literal: cx.tcx.mk_const(ty::Const {
-                    val: ty::ConstKind::Unevaluated(def_id, substs),
+                    val: ty::ConstKind::Unevaluated(def_id, substs, None),
                     ty: cx.tables().node_type(expr.hir_id),
                 }),
                 user_ty,
@@ -772,7 +778,7 @@
     }
 }
 
-fn convert_var(
+fn convert_var<'tcx>(
     cx: &mut Cx<'_, 'tcx>,
     expr: &'tcx hir::Expr<'tcx>,
     var_hir_id: hir::HirId,
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs
similarity index 75%
rename from src/librustc_mir/hair/cx/mod.rs
rename to src/librustc_mir_build/hair/cx/mod.rs
index 2e5ab33..497c661 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir_build/hair/cx/mod.rs
@@ -5,9 +5,9 @@
 use crate::hair::util::UserAnnotatedTyHelpers;
 use crate::hair::*;
 
-use crate::hair::constant::{lit_to_const, LitToConstError};
 use rustc::infer::InferCtxt;
 use rustc::middle::region;
+use rustc::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::Subst;
 use rustc::ty::subst::{GenericArg, InternalSubsts};
@@ -21,18 +21,18 @@
 use syntax::attr;
 
 #[derive(Clone)]
-pub struct Cx<'a, 'tcx> {
+crate struct Cx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'a InferCtxt<'a, 'tcx>,
 
-    pub root_lint_level: hir::HirId,
-    pub param_env: ty::ParamEnv<'tcx>,
+    crate root_lint_level: hir::HirId,
+    crate param_env: ty::ParamEnv<'tcx>,
 
     /// Identity `InternalSubsts` for use with const-evaluation.
-    pub identity_substs: &'tcx InternalSubsts<'tcx>,
+    crate identity_substs: &'tcx InternalSubsts<'tcx>,
 
-    pub region_scope_tree: &'tcx region::ScopeTree,
-    pub tables: &'a ty::TypeckTables<'tcx>,
+    crate region_scope_tree: &'tcx region::ScopeTree,
+    crate tables: &'a ty::TypeckTables<'tcx>,
 
     /// This is `Constness::Const` if we are compiling a `static`,
     /// `const`, or the body of a `const fn`.
@@ -42,7 +42,7 @@
     body_owner: DefId,
 
     /// What kind of body is being compiled.
-    pub body_owner_kind: hir::BodyOwnerKind,
+    crate body_owner_kind: hir::BodyOwnerKind,
 
     /// Whether this constant/function needs overflow checks.
     check_overflow: bool,
@@ -52,7 +52,7 @@
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
+    crate fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
         let tcx = infcx.tcx;
         let src_def_id = tcx.hir().local_def_id(src_id);
         let tables = tcx.typeck_tables_of(src_def_id);
@@ -92,42 +92,42 @@
         }
     }
 
-    pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
+    crate fn control_flow_destroyed(self) -> Vec<(Span, String)> {
         self.control_flow_destroyed
     }
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
     /// Normalizes `ast` into the appropriate "mirror" type.
-    pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
+    crate fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
         ast.make_mirror(self)
     }
 
-    pub fn usize_ty(&mut self) -> Ty<'tcx> {
+    crate fn usize_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.usize
     }
 
-    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
+    crate fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_usize(self.tcx, value)
     }
 
-    pub fn bool_ty(&mut self) -> Ty<'tcx> {
+    crate fn bool_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.bool
     }
 
-    pub fn unit_ty(&mut self) -> Ty<'tcx> {
+    crate fn unit_ty(&mut self) -> Ty<'tcx> {
         self.tcx.mk_unit()
     }
 
-    pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+    crate fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_bool(self.tcx, true)
     }
 
-    pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+    crate fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_bool(self.tcx, false)
     }
 
-    pub fn const_eval_literal(
+    crate fn const_eval_literal(
         &mut self,
         lit: &'tcx ast::LitKind,
         ty: Ty<'tcx>,
@@ -136,7 +136,7 @@
     ) -> &'tcx ty::Const<'tcx> {
         trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg);
 
-        match lit_to_const(lit, self.tcx, ty, neg) {
+        match self.tcx.at(sp).lit_to_const(LitToConstInput { lit, ty, neg }) {
             Ok(c) => c,
             Err(LitToConstError::UnparseableFloat) => {
                 // FIXME(#31407) this is only necessary because float parsing is buggy
@@ -151,15 +151,15 @@
         }
     }
 
-    pub fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+    crate fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
         let p = match self.tcx.hir().get(p.hir_id) {
             Node::Pat(p) | Node::Binding(p) => p,
             node => bug!("pattern became {:?}", node),
         };
-        Pat::from_hir(self.tcx, self.param_env.and(self.identity_substs), self.tables(), p)
+        Pat::from_hir(self.tcx, self.param_env, self.tables(), p)
     }
 
-    pub fn trait_method(
+    crate fn trait_method(
         &mut self,
         trait_def_id: DefId,
         method_name: Symbol,
@@ -168,6 +168,8 @@
     ) -> &'tcx ty::Const<'tcx> {
         let substs = self.tcx.mk_substs_trait(self_ty, params);
         for item in self.tcx.associated_items(trait_def_id) {
+            // The unhygienic comparison here is acceptable because this is only
+            // used on known traits.
             if item.kind == ty::AssocKind::Method && item.ident.name == method_name {
                 let method_ty = self.tcx.type_of(item.def_id);
                 let method_ty = method_ty.subst(self.tcx, substs);
@@ -178,32 +180,32 @@
         bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
-    pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
+    crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
         (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect()
     }
 
-    pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
+    crate fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
         ty.needs_drop(self.tcx, self.param_env)
     }
 
-    pub fn tcx(&self) -> TyCtxt<'tcx> {
+    crate fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
+    crate fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
         self.tables
     }
 
-    pub fn check_overflow(&self) -> bool {
+    crate fn check_overflow(&self) -> bool {
         self.check_overflow
     }
 
-    pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
+    crate fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
         self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span)
     }
 }
 
-impl UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
+impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx()
     }
diff --git a/src/librustc_mir/hair/cx/to_ref.rs b/src/librustc_mir_build/hair/cx/to_ref.rs
similarity index 98%
rename from src/librustc_mir/hair/cx/to_ref.rs
rename to src/librustc_mir_build/hair/cx/to_ref.rs
index d6859e3..6cf8122 100644
--- a/src/librustc_mir/hair/cx/to_ref.rs
+++ b/src/librustc_mir_build/hair/cx/to_ref.rs
@@ -2,7 +2,7 @@
 
 use rustc_hir as hir;
 
-pub trait ToRef {
+crate trait ToRef {
     type Output;
     fn to_ref(self) -> Self::Output;
 }
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs
similarity index 85%
rename from src/librustc_mir/hair/mod.rs
rename to src/librustc_mir_build/hair/mod.rs
index cde91cc..0f2c761 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir_build/hair/mod.rs
@@ -16,34 +16,34 @@
 use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
-mod constant;
-pub mod cx;
+crate mod constant;
+crate mod cx;
 
-pub mod pattern;
-pub(crate) use self::pattern::PatTyProj;
-pub use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
+crate mod pattern;
+crate use self::pattern::PatTyProj;
+crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
 
 mod util;
 
 #[derive(Copy, Clone, Debug)]
-pub enum LintLevel {
+crate enum LintLevel {
     Inherited,
     Explicit(hir::HirId),
 }
 
 #[derive(Clone, Debug)]
-pub struct Block<'tcx> {
-    pub targeted_by_break: bool,
-    pub region_scope: region::Scope,
-    pub opt_destruction_scope: Option<region::Scope>,
-    pub span: Span,
-    pub stmts: Vec<StmtRef<'tcx>>,
-    pub expr: Option<ExprRef<'tcx>>,
-    pub safety_mode: BlockSafety,
+crate struct Block<'tcx> {
+    crate targeted_by_break: bool,
+    crate region_scope: region::Scope,
+    crate opt_destruction_scope: Option<region::Scope>,
+    crate span: Span,
+    crate stmts: Vec<StmtRef<'tcx>>,
+    crate expr: Option<ExprRef<'tcx>>,
+    crate safety_mode: BlockSafety,
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BlockSafety {
+crate enum BlockSafety {
     Safe,
     ExplicitUnsafe(hir::HirId),
     PushUnsafe,
@@ -51,18 +51,18 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtRef<'tcx> {
+crate enum StmtRef<'tcx> {
     Mirror(Box<Stmt<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct Stmt<'tcx> {
-    pub kind: StmtKind<'tcx>,
-    pub opt_destruction_scope: Option<region::Scope>,
+crate struct Stmt<'tcx> {
+    crate kind: StmtKind<'tcx>,
+    crate opt_destruction_scope: Option<region::Scope>,
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtKind<'tcx> {
+crate enum StmtKind<'tcx> {
     Expr {
         /// scope for this statement; may be used as lifetime of temporaries
         scope: region::Scope,
@@ -112,23 +112,23 @@
 /// example, method calls and overloaded operators are absent: they are
 /// expected to be converted into `Expr::Call` instances.
 #[derive(Clone, Debug)]
-pub struct Expr<'tcx> {
+crate struct Expr<'tcx> {
     /// type of this expression
-    pub ty: Ty<'tcx>,
+    crate ty: Ty<'tcx>,
 
     /// lifetime of this expression if it should be spilled into a
     /// temporary; should be None only if in a constant context
-    pub temp_lifetime: Option<region::Scope>,
+    crate temp_lifetime: Option<region::Scope>,
 
     /// span of the expression in the source
-    pub span: Span,
+    crate span: Span,
 
     /// kind of expression
-    pub kind: ExprKind<'tcx>,
+    crate kind: ExprKind<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprKind<'tcx> {
+crate enum ExprKind<'tcx> {
     Scope {
         region_scope: region::Scope,
         lint_level: LintLevel,
@@ -288,37 +288,37 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprRef<'tcx> {
+crate enum ExprRef<'tcx> {
     Hair(&'tcx hir::Expr<'tcx>),
     Mirror(Box<Expr<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldExprRef<'tcx> {
-    pub name: Field,
-    pub expr: ExprRef<'tcx>,
+crate struct FieldExprRef<'tcx> {
+    crate name: Field,
+    crate expr: ExprRef<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct FruInfo<'tcx> {
-    pub base: ExprRef<'tcx>,
-    pub field_types: Vec<Ty<'tcx>>,
+crate struct FruInfo<'tcx> {
+    crate base: ExprRef<'tcx>,
+    crate field_types: Vec<Ty<'tcx>>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Arm<'tcx> {
-    pub pattern: Pat<'tcx>,
-    pub guard: Option<Guard<'tcx>>,
-    pub body: ExprRef<'tcx>,
-    pub lint_level: LintLevel,
-    pub scope: region::Scope,
-    pub span: Span,
+crate struct Arm<'tcx> {
+    crate pattern: Pat<'tcx>,
+    crate guard: Option<Guard<'tcx>>,
+    crate body: ExprRef<'tcx>,
+    crate lint_level: LintLevel,
+    crate scope: region::Scope,
+    crate span: Span,
 }
 
-impl Arm<'tcx> {
+impl<'tcx> Arm<'tcx> {
     // HACK(or_patterns; Centril | dlrobertson): Remove this and
     // correctly handle each case in which this method is used.
-    pub fn top_pats_hack(&self) -> &[Pat<'tcx>] {
+    crate fn top_pats_hack(&self) -> &[Pat<'tcx>] {
         match &*self.pattern.kind {
             PatKind::Or { pats } => pats,
             _ => std::slice::from_ref(&self.pattern),
@@ -327,18 +327,18 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum Guard<'tcx> {
+crate enum Guard<'tcx> {
     If(ExprRef<'tcx>),
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum LogicalOp {
+crate enum LogicalOp {
     And,
     Or,
 }
 
 impl<'tcx> ExprRef<'tcx> {
-    pub fn span(&self) -> Span {
+    crate fn span(&self) -> Span {
         match self {
             ExprRef::Hair(expr) => expr.span,
             ExprRef::Mirror(expr) => expr.span,
@@ -361,7 +361,7 @@
 /// mirrored. This allows a single AST node from the compiler to
 /// expand into one or more Hair nodes, which lets the Hair nodes be
 /// simpler.
-pub trait Mirror<'tcx> {
+crate trait Mirror<'tcx> {
     type Output;
 
     fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
@@ -378,7 +378,7 @@
 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
     type Output = Expr<'tcx>;
 
-    fn make_mirror(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
+    fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
         match self {
             ExprRef::Hair(h) => h.make_mirror(hir),
             ExprRef::Mirror(m) => *m,
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
similarity index 98%
rename from src/librustc_mir/hair/pattern/_match.rs
rename to src/librustc_mir_build/hair/pattern/_match.rs
index 03120e8..a2ce224 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -229,7 +229,7 @@
 use self::Usefulness::*;
 use self::WitnessPreference::*;
 
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 
 use super::{compare_const_vals, PatternFoldable, PatternFolder};
@@ -243,7 +243,6 @@
 use rustc::lint;
 use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
 use rustc::mir::Field;
-use rustc::util::captures::Captures;
 use rustc::util::common::ErrorReported;
 
 use rustc_span::{Span, DUMMY_SP};
@@ -260,7 +259,7 @@
 use std::ops::RangeInclusive;
 use std::u128;
 
-pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
+crate fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
     LiteralExpander { tcx: cx.tcx, param_env: cx.param_env }.fold_pattern(&pat)
 }
 
@@ -269,7 +268,7 @@
     param_env: ty::ParamEnv<'tcx>,
 }
 
-impl LiteralExpander<'tcx> {
+impl<'tcx> LiteralExpander<'tcx> {
     /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice.
     ///
     /// `crty` and `rty` can differ because you can use array constants in the presence of slice
@@ -323,7 +322,7 @@
     }
 }
 
-impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
+impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> {
     fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
         debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind, pat.kind);
         match (&pat.ty.kind, &*pat.kind) {
@@ -381,10 +380,10 @@
 /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
 /// works well.
 #[derive(Debug, Clone)]
-pub struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
+crate struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
 
 impl<'p, 'tcx> PatStack<'p, 'tcx> {
-    pub fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
+    crate fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
         PatStack(smallvec![pat])
     }
 
@@ -472,15 +471,15 @@
 
 /// A 2D matrix.
 #[derive(Clone)]
-pub struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
+crate struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
 
 impl<'p, 'tcx> Matrix<'p, 'tcx> {
-    pub fn empty() -> Self {
+    crate fn empty() -> Self {
         Matrix(vec![])
     }
 
     /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
-    pub fn push(&mut self, row: PatStack<'p, 'tcx>) {
+    crate fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if let Some(rows) = row.expand_or_pat() {
             self.0.extend(rows);
         } else {
@@ -569,39 +568,29 @@
     }
 }
 
-pub struct MatchCheckCtxt<'a, 'tcx> {
-    pub tcx: TyCtxt<'tcx>,
+crate struct MatchCheckCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
     /// The module in which the match occurs. This is necessary for
     /// checking inhabited-ness of types because whether a type is (visibly)
     /// inhabited can depend on whether it was defined in the current module or
     /// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
     /// outside it's module and should not be matchable with an empty match
     /// statement.
-    pub module: DefId,
+    crate module: DefId,
     param_env: ty::ParamEnv<'tcx>,
-    pub pattern_arena: &'a TypedArena<Pat<'tcx>>,
-    pub byte_array_map: FxHashMap<*const Pat<'tcx>, Vec<&'a Pat<'tcx>>>,
+    crate pattern_arena: &'a TypedArena<Pat<'tcx>>,
 }
 
 impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
-    pub fn create_and_enter<F, R>(
+    crate fn create_and_enter<R>(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         module: DefId,
-        f: F,
-    ) -> R
-    where
-        F: for<'b> FnOnce(MatchCheckCtxt<'b, 'tcx>) -> R,
-    {
+        f: impl for<'b> FnOnce(MatchCheckCtxt<'b, 'tcx>) -> R,
+    ) -> R {
         let pattern_arena = TypedArena::default();
 
-        f(MatchCheckCtxt {
-            tcx,
-            param_env,
-            module,
-            pattern_arena: &pattern_arena,
-            byte_array_map: FxHashMap::default(),
-        })
+        f(MatchCheckCtxt { tcx, param_env, module, pattern_arena: &pattern_arena })
     }
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
@@ -613,7 +602,7 @@
     }
 
     // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
-    pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
+    crate fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind {
             ty::Adt(def, ..) => {
                 def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
@@ -773,13 +762,13 @@
         cx: &MatchCheckCtxt<'a, 'tcx>,
         adt: &'tcx ty::AdtDef,
     ) -> VariantIdx {
-        match self {
-            Variant(id) => adt.variant_index_with_id(*id),
+        match *self {
+            Variant(id) => adt.variant_index_with_id(id),
             Single => {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
             }
-            ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
+            ConstantValue(c) => cx.tcx.destructure_const(cx.param_env.and(c)).variant,
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
         }
     }
@@ -1058,7 +1047,7 @@
 }
 
 #[derive(Clone, Debug)]
-pub enum Usefulness<'tcx, 'p> {
+crate enum Usefulness<'tcx, 'p> {
     /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
     Useful(Vec<&'p Pat<'tcx>>),
     /// Carries a list of witnesses of non-exhaustiveness.
@@ -1146,7 +1135,7 @@
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum WitnessPreference {
+crate enum WitnessPreference {
     ConstructWitness,
     LeaveOutWitness,
 }
@@ -1190,10 +1179,10 @@
 ///
 /// The final `Pair(Some(_), true)` is then the resulting witness.
 #[derive(Clone, Debug)]
-pub struct Witness<'tcx>(Vec<Pat<'tcx>>);
+crate struct Witness<'tcx>(Vec<Pat<'tcx>>);
 
 impl<'tcx> Witness<'tcx> {
-    pub fn single_pattern(self) -> Pat<'tcx> {
+    crate fn single_pattern(self) -> Pat<'tcx> {
         assert_eq!(self.0.len(), 1);
         self.0.into_iter().next().unwrap()
     }
@@ -1358,9 +1347,9 @@
 /// around the (offset) space: i.e., `range.lo <= range.hi`.
 #[derive(Clone, Debug)]
 struct IntRange<'tcx> {
-    pub range: RangeInclusive<u128>,
-    pub ty: Ty<'tcx>,
-    pub span: Span,
+    range: RangeInclusive<u128>,
+    ty: Ty<'tcx>,
+    span: Span,
 }
 
 impl<'tcx> IntRange<'tcx> {
@@ -1541,7 +1530,7 @@
         // 2       --------   // 2 -------
         let (lo, hi) = self.boundaries();
         let (other_lo, other_hi) = other.boundaries();
-        (lo == other_hi || hi == other_lo)
+        lo == other_hi || hi == other_lo
     }
 
     fn to_pat(&self, tcx: TyCtxt<'tcx>) -> Pat<'tcx> {
@@ -1631,7 +1620,7 @@
 /// relation to preceding patterns, it is not reachable) and exhaustiveness
 /// checking (if a wildcard pattern is useful in relation to a matrix, the
 /// matrix isn't exhaustive).
-pub fn is_useful<'p, 'tcx>(
+crate fn is_useful<'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
@@ -2238,7 +2227,7 @@
     split_ctors
 }
 
-fn lint_overlapping_patterns(
+fn lint_overlapping_patterns<'tcx>(
     tcx: TyCtxt<'tcx>,
     hir_id: Option<HirId>,
     ctor_range: IntRange<'tcx>,
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
similarity index 80%
rename from src/librustc_mir/hair/pattern/check_match.rs
rename to src/librustc_mir_build/hair/pattern/check_match.rs
index ca7912b..49b7c2d 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -4,21 +4,21 @@
 
 use super::{PatCtxt, PatKind, PatternError};
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::lint;
-use rustc::session::Session;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
+use rustc::hir::map::Map;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_error_codes::*;
-use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{HirId, Pat};
+use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
+use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::Mutability;
-use syntax::feature_gate::feature_err;
 
 use std::slice;
 
@@ -28,12 +28,8 @@
         Some(id) => tcx.hir().body_owned_by(id),
     };
 
-    let mut visitor = MatchVisitor {
-        tcx,
-        tables: tcx.body_tables(body_id),
-        param_env: tcx.param_env(def_id),
-        identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
-    };
+    let mut visitor =
+        MatchVisitor { tcx, tables: tcx.body_tables(body_id), param_env: tcx.param_env(def_id) };
     visitor.visit_body(tcx.hir().body(body_id));
 }
 
@@ -45,11 +41,12 @@
     tcx: TyCtxt<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    identity_substs: SubstsRef<'tcx>,
 }
 
 impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -71,18 +68,13 @@
             hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
         };
         self.check_irrefutable(&loc.pat, msg, sp);
-
-        // Check legality of move bindings and `@` patterns.
         self.check_patterns(false, &loc.pat);
     }
 
-    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
-        intravisit::walk_body(self, body);
-
-        for param in body.params {
-            self.check_irrefutable(&param.pat, "function argument", None);
-            self.check_patterns(false, &param.pat);
-        }
+    fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
+        intravisit::walk_param(self, param);
+        self.check_irrefutable(&param.pat, "function argument", None);
+        self.check_patterns(false, &param.pat);
     }
 }
 
@@ -116,7 +108,7 @@
     }
 
     fn span_e0158(&self, span: Span, text: &str) {
-        span_err!(self.tcx.sess, span, E0158, "{}", text)
+        struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit();
     }
 }
 
@@ -127,6 +119,25 @@
         if !self.tcx.features().bindings_after_at {
             check_legality_of_bindings_in_at_patterns(self, pat);
         }
+        check_for_bindings_named_same_as_variants(self, pat);
+    }
+
+    fn lower_pattern<'p>(
+        &self,
+        cx: &mut MatchCheckCtxt<'p, 'tcx>,
+        pat: &'tcx hir::Pat<'tcx>,
+        have_errors: &mut bool,
+    ) -> (&'p super::Pat<'tcx>, Ty<'tcx>) {
+        let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
+        patcx.include_lint_checks();
+        let pattern = patcx.lower_pattern(pat);
+        let pattern_ty = pattern.ty;
+        let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
+        if !patcx.errors.is_empty() {
+            *have_errors = true;
+            patcx.report_inlining_errors(pat.span);
+        }
+        (pattern, pattern_ty)
     }
 
     fn check_match(
@@ -136,11 +147,8 @@
         source: hir::MatchSource,
     ) {
         for arm in arms {
-            // First, check legality of move bindings.
+            // Check the arm for some things unrelated to exhaustiveness.
             self.check_patterns(arm.guard.is_some(), &arm.pat);
-
-            // Second, perform some lints.
-            check_for_bindings_named_same_as_variants(self, &arm.pat);
         }
 
         let module = self.tcx.hir().get_module_parent(scrut.hir_id);
@@ -149,20 +157,8 @@
 
             let inlined_arms: Vec<_> = arms
                 .iter()
-                .map(|arm| {
-                    let mut patcx = PatCtxt::new(
-                        self.tcx,
-                        self.param_env.and(self.identity_substs),
-                        self.tables,
-                    );
-                    patcx.include_lint_checks();
-                    let pattern = patcx.lower_pattern(&arm.pat);
-                    let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
-                    if !patcx.errors.is_empty() {
-                        patcx.report_inlining_errors(arm.pat.span);
-                        have_errors = true;
-                    }
-                    (pattern, &*arm.pat, arm.guard.is_some())
+                .map(|hir::Arm { pat, guard, .. }| {
+                    (self.lower_pattern(cx, pat, &mut have_errors).0, pat.hir_id, guard.is_some())
                 })
                 .collect();
 
@@ -186,12 +182,7 @@
     fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>) {
         let module = self.tcx.hir().get_module_parent(pat.hir_id);
         MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
-            let mut patcx =
-                PatCtxt::new(self.tcx, self.param_env.and(self.identity_substs), self.tables);
-            patcx.include_lint_checks();
-            let pattern = patcx.lower_pattern(pat);
-            let pattern_ty = pattern.ty;
-            let pattern = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
+            let (pattern, pattern_ty) = self.lower_pattern(cx, pat, &mut false);
             let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(pattern)].into_iter().collect();
 
             let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) {
@@ -291,24 +282,26 @@
                             variant.ident == ident && variant.ctor_kind == CtorKind::Const
                         })
                     {
-                        // FIXME(Centril): Should be a lint?
                         let ty_path = cx.tcx.def_path_str(edef.did);
-                        let mut err = struct_span_warn!(
-                            cx.tcx.sess,
-                            p.span,
-                            E0170,
-                            "pattern binding `{}` is named the same as one \
-                             of the variants of the type `{}`",
-                            ident,
-                            ty_path
-                        );
-                        err.span_suggestion(
-                            p.span,
-                            "to match on the variant, qualify the path",
-                            format!("{}::{}", ty_path, ident),
-                            Applicability::MachineApplicable,
-                        );
-                        err.emit();
+                        cx.tcx
+                            .struct_span_lint_hir(
+                                BINDINGS_WITH_VARIANT_NAME,
+                                p.hir_id,
+                                p.span,
+                                &format!(
+                                    "pattern binding `{}` is named the same as one \
+                                    of the variants of the type `{}`",
+                                    ident, ty_path
+                                ),
+                            )
+                            .code(error_code!(E0170))
+                            .span_suggestion(
+                                p.span,
+                                "to match on the variant, qualify the path",
+                                format!("{}::{}", ty_path, ident),
+                                Applicability::MachineApplicable,
+                            )
+                            .emit();
                     }
                 }
             }
@@ -317,79 +310,63 @@
 }
 
 /// Checks for common cases of "catchall" patterns that may not be intended as such.
-fn pat_is_catchall(pat: &Pat<'_>) -> bool {
-    match pat.kind {
-        hir::PatKind::Binding(.., None) => true,
-        hir::PatKind::Binding(.., Some(ref s)) => pat_is_catchall(s),
-        hir::PatKind::Ref(ref s, _) => pat_is_catchall(s),
-        hir::PatKind::Tuple(ref v, _) => v.iter().all(|p| pat_is_catchall(&p)),
+fn pat_is_catchall(pat: &super::Pat<'_>) -> bool {
+    use super::PatKind::*;
+    match &*pat.kind {
+        Binding { subpattern: None, .. } => true,
+        Binding { subpattern: Some(s), .. } | Deref { subpattern: s } => pat_is_catchall(s),
+        Leaf { subpatterns: s } => s.iter().all(|p| pat_is_catchall(&p.pattern)),
         _ => false,
     }
 }
 
+fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
+    let mut err = tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern");
+    if let Some(catchall) = catchall {
+        // We had a catchall pattern, hint at that.
+        err.span_label(span, "unreachable pattern");
+        err.span_label(catchall, "matches any value");
+    }
+    err.emit();
+}
+
+fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::MatchSource) {
+    let msg = match source {
+        hir::MatchSource::IfLetDesugar { .. } => "irrefutable if-let pattern",
+        hir::MatchSource::WhileLetDesugar => "irrefutable while-let pattern",
+        _ => bug!(),
+    };
+    tcx.lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, msg);
+}
+
 /// Check for unreachable patterns.
 fn check_arms<'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'p, 'tcx>,
-    arms: &[(&'p super::Pat<'tcx>, &hir::Pat<'_>, bool)],
+    arms: &[(&'p super::Pat<'tcx>, HirId, bool)],
     source: hir::MatchSource,
 ) -> Matrix<'p, 'tcx> {
     let mut seen = Matrix::empty();
     let mut catchall = None;
-    for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() {
+    for (arm_index, (pat, id, has_guard)) in arms.iter().copied().enumerate() {
         let v = PatStack::from_pattern(pat);
-
-        match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id, true) {
+        match is_useful(cx, &seen, &v, LeaveOutWitness, id, true) {
             NotUseful => {
                 match source {
                     hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
 
                     hir::MatchSource::IfLetDesugar { .. } | hir::MatchSource::WhileLetDesugar => {
-                        // check which arm we're on.
+                        // Check which arm we're on.
                         match arm_index {
                             // The arm with the user-specified pattern.
-                            0 => {
-                                cx.tcx.lint_hir(
-                                    lint::builtin::UNREACHABLE_PATTERNS,
-                                    hir_pat.hir_id,
-                                    pat.span,
-                                    "unreachable pattern",
-                                );
-                            }
+                            0 => unreachable_pattern(cx.tcx, pat.span, id, None),
                             // The arm with the wildcard pattern.
-                            1 => {
-                                let msg = match source {
-                                    hir::MatchSource::IfLetDesugar { .. } => {
-                                        "irrefutable if-let pattern"
-                                    }
-                                    hir::MatchSource::WhileLetDesugar => {
-                                        "irrefutable while-let pattern"
-                                    }
-                                    _ => bug!(),
-                                };
-                                cx.tcx.lint_hir(
-                                    lint::builtin::IRREFUTABLE_LET_PATTERNS,
-                                    hir_pat.hir_id,
-                                    pat.span,
-                                    msg,
-                                );
-                            }
+                            1 => irrefutable_let_pattern(cx.tcx, pat.span, id, source),
                             _ => bug!(),
                         }
                     }
 
                     hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
-                        let mut err = cx.tcx.struct_span_lint_hir(
-                            lint::builtin::UNREACHABLE_PATTERNS,
-                            hir_pat.hir_id,
-                            pat.span,
-                            "unreachable pattern",
-                        );
-                        // if we had a catchall pattern, hint at that
-                        if let Some(catchall) = catchall {
-                            err.span_label(pat.span, "unreachable pattern");
-                            err.span_label(catchall, "matches any value");
-                        }
-                        err.emit();
+                        unreachable_pattern(cx.tcx, pat.span, id, catchall);
                     }
 
                     // Unreachable patterns in try and await expressions occur when one of
@@ -399,19 +376,14 @@
             }
             Useful(unreachable_subpatterns) => {
                 for pat in unreachable_subpatterns {
-                    cx.tcx.lint_hir(
-                        lint::builtin::UNREACHABLE_PATTERNS,
-                        hir_pat.hir_id,
-                        pat.span,
-                        "unreachable pattern",
-                    );
+                    unreachable_pattern(cx.tcx, pat.span, id, None);
                 }
             }
             UsefulWithWitness(_) => bug!(),
         }
         if !has_guard {
             seen.push(v);
-            if catchall.is_none() && pat_is_catchall(hir_pat) {
+            if catchall.is_none() && pat_is_catchall(pat) {
                 catchall = Some(pat.span);
             }
         }
@@ -728,7 +700,9 @@
     }
 
     impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
diff --git a/src/librustc_mir/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
similarity index 87%
rename from src/librustc_mir/hair/pattern/const_to_pat.rs
rename to src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 75b25f0..a21a0ee 100644
--- a/src/librustc_mir/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -1,5 +1,3 @@
-use crate::const_eval::const_variant_index;
-
 use rustc::infer::InferCtxt;
 use rustc::lint;
 use rustc::mir::Field;
@@ -167,18 +165,14 @@
         let tcx = self.tcx();
         let param_env = self.param_env;
 
-        let adt_subpattern = |i, variant_opt| {
-            let field = Field::new(i);
-            let val = crate::const_eval::const_field(tcx, param_env, variant_opt, field, cv);
-            self.recur(val)
-        };
-        let adt_subpatterns = |n, variant_opt| {
-            (0..n)
-                .map(|i| {
-                    let field = Field::new(i);
-                    FieldPat { field, pattern: adt_subpattern(i, variant_opt) }
+        let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| {
+            vals.iter()
+                .enumerate()
+                .map(|(idx, val)| {
+                    let field = Field::new(idx);
+                    FieldPat { field, pattern: self.recur(val) }
                 })
-                .collect::<Vec<_>>()
+                .collect()
         };
 
         let kind = match cv.ty.kind {
@@ -235,21 +229,28 @@
                 PatKind::Wild
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
-                let variant_index = const_variant_index(tcx, self.param_env, cv);
-                let subpatterns = adt_subpatterns(
-                    adt_def.variants[variant_index].fields.len(),
-                    Some(variant_index),
-                );
-                PatKind::Variant { adt_def, substs, variant_index, subpatterns }
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Variant {
+                    adt_def,
+                    substs,
+                    variant_index: destructured.variant,
+                    subpatterns: field_pats(destructured.fields),
+                }
             }
-            ty::Adt(adt_def, _) => {
-                let struct_var = adt_def.non_enum_variant();
-                PatKind::Leaf { subpatterns: adt_subpatterns(struct_var.fields.len(), None) }
+            ty::Adt(_, _) => {
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
             }
-            ty::Tuple(fields) => PatKind::Leaf { subpatterns: adt_subpatterns(fields.len(), None) },
-            ty::Array(_, n) => PatKind::Array {
-                prefix: (0..n.eval_usize(tcx, self.param_env))
-                    .map(|i| adt_subpattern(i as usize, None))
+            ty::Tuple(_) => {
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
+            }
+            ty::Array(..) => PatKind::Array {
+                prefix: tcx
+                    .destructure_const(param_env.and(cv))
+                    .fields
+                    .iter()
+                    .map(|val| self.recur(val))
                     .collect(),
                 slice: None,
                 suffix: Vec::new(),
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
similarity index 82%
rename from src/librustc_mir/hair/pattern/mod.rs
rename to src/librustc_mir_build/hair/pattern/mod.rs
index bac40a0..2657050 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -6,16 +6,17 @@
 
 pub(crate) use self::check_match::check_match;
 
-use crate::hair::constant::*;
 use crate::hair::util::UserAnnotatedTyHelpers;
 
 use rustc::mir::interpret::{get_slice_bytes, sign_extend, ConstValue, ErrorHandled};
+use rustc::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc::mir::UserTypeProjection;
 use rustc::mir::{BorrowKind, Field, Mutability};
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::{GenericArg, SubstsRef};
 use rustc::ty::{self, AdtDef, DefIdTree, Region, Ty, TyCtxt, UserType};
 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -27,10 +28,8 @@
 use std::cmp::Ordering;
 use std::fmt;
 
-use rustc_error_codes::*;
-
 #[derive(Clone, Debug)]
-pub enum PatternError {
+crate enum PatternError {
     AssocConstInPattern(Span),
     StaticInPattern(Span),
     FloatBug,
@@ -38,22 +37,22 @@
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BindingMode {
+crate enum BindingMode {
     ByValue,
     ByRef(BorrowKind),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldPat<'tcx> {
-    pub field: Field,
-    pub pattern: Pat<'tcx>,
+crate struct FieldPat<'tcx> {
+    crate field: Field,
+    crate pattern: Pat<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Pat<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub span: Span,
-    pub kind: Box<PatKind<'tcx>>,
+crate struct Pat<'tcx> {
+    crate ty: Ty<'tcx>,
+    crate span: Span,
+    crate kind: Box<PatKind<'tcx>>,
 }
 
 impl<'tcx> Pat<'tcx> {
@@ -63,8 +62,8 @@
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct PatTyProj<'tcx> {
-    pub user_ty: CanonicalUserType<'tcx>,
+crate struct PatTyProj<'tcx> {
+    crate user_ty: CanonicalUserType<'tcx>,
 }
 
 impl<'tcx> PatTyProj<'tcx> {
@@ -90,8 +89,8 @@
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct Ascription<'tcx> {
-    pub user_ty: PatTyProj<'tcx>,
+crate struct Ascription<'tcx> {
+    crate user_ty: PatTyProj<'tcx>,
     /// Variance to use when relating the type `user_ty` to the **type of the value being
     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
     /// have a type that is some subtype of the ascribed type.
@@ -110,12 +109,12 @@
     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
     /// of the old type-check for now. See #57280 for details.
-    pub variance: ty::Variance,
-    pub user_ty_span: Span,
+    crate variance: ty::Variance,
+    crate user_ty_span: Span,
 }
 
 #[derive(Clone, Debug)]
-pub enum PatKind<'tcx> {
+crate enum PatKind<'tcx> {
     Wild,
 
     AscribeUserType {
@@ -183,10 +182,10 @@
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct PatRange<'tcx> {
-    pub lo: &'tcx ty::Const<'tcx>,
-    pub hi: &'tcx ty::Const<'tcx>,
-    pub end: RangeEnd,
+crate struct PatRange<'tcx> {
+    crate lo: &'tcx ty::Const<'tcx>,
+    crate hi: &'tcx ty::Const<'tcx>,
+    crate end: RangeEnd,
 }
 
 impl<'tcx> fmt::Display for Pat<'tcx> {
@@ -341,23 +340,22 @@
     }
 }
 
-pub struct PatCtxt<'a, 'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-    pub param_env: ty::ParamEnv<'tcx>,
-    pub tables: &'a ty::TypeckTables<'tcx>,
-    pub substs: SubstsRef<'tcx>,
-    pub errors: Vec<PatternError>,
+crate struct PatCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
+    crate param_env: ty::ParamEnv<'tcx>,
+    crate tables: &'a ty::TypeckTables<'tcx>,
+    crate errors: Vec<PatternError>,
     include_lint_checks: bool,
 }
 
 impl<'a, 'tcx> Pat<'tcx> {
-    pub fn from_hir(
+    crate fn from_hir(
         tcx: TyCtxt<'tcx>,
-        param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
         tables: &'a ty::TypeckTables<'tcx>,
         pat: &'tcx hir::Pat<'tcx>,
     ) -> Self {
-        let mut pcx = PatCtxt::new(tcx, param_env_and_substs, tables);
+        let mut pcx = PatCtxt::new(tcx, param_env, tables);
         let result = pcx.lower_pattern(pat);
         if !pcx.errors.is_empty() {
             let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
@@ -369,27 +367,20 @@
 }
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
-    pub fn new(
+    crate fn new(
         tcx: TyCtxt<'tcx>,
-        param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
         tables: &'a ty::TypeckTables<'tcx>,
     ) -> Self {
-        PatCtxt {
-            tcx,
-            param_env: param_env_and_substs.param_env,
-            tables,
-            substs: param_env_and_substs.value,
-            errors: vec![],
-            include_lint_checks: false,
-        }
+        PatCtxt { tcx, param_env, tables, errors: vec![], include_lint_checks: false }
     }
 
-    pub fn include_lint_checks(&mut self) -> &mut Self {
+    crate fn include_lint_checks(&mut self) -> &mut Self {
         self.include_lint_checks = true;
         self
     }
 
-    pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+    crate fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
         // pattern has the type that results *after* dereferencing. For example, in this code:
         //
@@ -428,14 +419,87 @@
         expr: &'tcx hir::Expr<'tcx>,
     ) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
         match self.lower_lit(expr) {
-            PatKind::AscribeUserType {
-                ascription: lo_ascription,
-                subpattern: Pat { kind: box kind, .. },
-            } => (kind, Some(lo_ascription)),
+            PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => {
+                (kind, Some(ascription))
+            }
             kind => (kind, None),
         }
     }
 
+    fn lower_pattern_range(
+        &mut self,
+        ty: Ty<'tcx>,
+        lo: &'tcx ty::Const<'tcx>,
+        hi: &'tcx ty::Const<'tcx>,
+        end: RangeEnd,
+        span: Span,
+    ) -> PatKind<'tcx> {
+        assert_eq!(lo.ty, ty);
+        assert_eq!(hi.ty, ty);
+        let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
+        match (end, cmp) {
+            // `x..y` where `x < y`.
+            // Non-empty because the range includes at least `x`.
+            (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            // `x..y` where `x >= y`. The range is empty => error.
+            (RangeEnd::Excluded, _) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0579,
+                    "lower range bound must be less than upper"
+                )
+                .emit();
+                PatKind::Wild
+            }
+            // `x..=y` where `x == y`.
+            (RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo },
+            // `x..=y` where `x < y`.
+            (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            // `x..=y` where `x > y` hence the range is empty => error.
+            (RangeEnd::Included, _) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0030,
+                    "lower range bound must be less than or equal to upper"
+                );
+                err.span_label(span, "lower bound larger than upper bound");
+                if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                    err.note(
+                        "When matching against a range, the compiler \
+                              verifies that the range is non-empty. Range \
+                              patterns include both end-points, so this is \
+                              equivalent to requiring the start of the range \
+                              to be less than or equal to the end of the range.",
+                    );
+                }
+                err.emit();
+                PatKind::Wild
+            }
+        }
+    }
+
+    fn normalize_range_pattern_ends(
+        &self,
+        ty: Ty<'tcx>,
+        lo: Option<&PatKind<'tcx>>,
+        hi: Option<&PatKind<'tcx>>,
+    ) -> Option<(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>)> {
+        match (lo, hi) {
+            (Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
+                Some((lo, hi))
+            }
+            (Some(PatKind::Constant { value: lo }), None) => {
+                Some((lo, ty.numeric_max_val(self.tcx)?))
+            }
+            (None, Some(PatKind::Constant { value: hi })) => {
+                Some((ty.numeric_min_val(self.tcx)?, hi))
+            }
+            _ => None,
+        }
+    }
+
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let mut ty = self.tables.node_type(pat.hir_id);
 
@@ -450,64 +514,20 @@
             hir::PatKind::Lit(ref value) => self.lower_lit(value),
 
             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
-                let (lo, lo_ascription) = self.lower_range_expr(lo_expr);
-                let (hi, hi_ascription) = self.lower_range_expr(hi_expr);
+                let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
+                let lo_span = lo_expr.map_or(pat.span, |e| e.span);
+                let lo = lo_expr.map(|e| self.lower_range_expr(e));
+                let hi = hi_expr.map(|e| self.lower_range_expr(e));
 
-                let mut kind = match (lo, hi) {
-                    (PatKind::Constant { value: lo }, PatKind::Constant { value: hi }) => {
-                        assert_eq!(lo.ty, ty);
-                        assert_eq!(hi.ty, ty);
-                        let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
-                        match (end, cmp) {
-                            (RangeEnd::Excluded, Some(Ordering::Less)) => {
-                                PatKind::Range(PatRange { lo, hi, end })
-                            }
-                            (RangeEnd::Excluded, _) => {
-                                span_err!(
-                                    self.tcx.sess,
-                                    lo_expr.span,
-                                    E0579,
-                                    "lower range bound must be less than upper",
-                                );
-                                PatKind::Wild
-                            }
-                            (RangeEnd::Included, Some(Ordering::Equal)) => {
-                                PatKind::Constant { value: lo }
-                            }
-                            (RangeEnd::Included, Some(Ordering::Less)) => {
-                                PatKind::Range(PatRange { lo, hi, end })
-                            }
-                            (RangeEnd::Included, _) => {
-                                let mut err = struct_span_err!(
-                                    self.tcx.sess,
-                                    lo_expr.span,
-                                    E0030,
-                                    "lower range bound must be less than or equal to upper"
-                                );
-                                err.span_label(lo_expr.span, "lower bound larger than upper bound");
-                                if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                                    err.note(
-                                        "When matching against a range, the compiler \
-                                              verifies that the range is non-empty. Range \
-                                              patterns include both end-points, so this is \
-                                              equivalent to requiring the start of the range \
-                                              to be less than or equal to the end of the range.",
-                                    );
-                                }
-                                err.emit();
-                                PatKind::Wild
-                            }
-                        }
-                    }
-                    ref pats => {
-                        self.tcx.sess.delay_span_bug(
-                            pat.span,
-                            &format!(
-                                "found bad range pattern `{:?}` outside of error recovery",
-                                pats,
-                            ),
+                let (lp, hp) = (lo.as_ref().map(|x| &x.0), hi.as_ref().map(|x| &x.0));
+                let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) {
+                    Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span),
+                    None => {
+                        let msg = &format!(
+                            "found bad range pattern `{:?}` outside of error recovery",
+                            (&lo, &hi),
                         );
-
+                        self.tcx.sess.delay_span_bug(pat.span, msg);
                         PatKind::Wild
                     }
                 };
@@ -515,12 +535,10 @@
                 // If we are handling a range with associated constants (e.g.
                 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
                 // constants somewhere. Have them on the range pattern.
-                for ascription in &[lo_ascription, hi_ascription] {
-                    if let Some(ascription) = ascription {
-                        kind = PatKind::AscribeUserType {
-                            ascription: *ascription,
-                            subpattern: Pat { span: pat.span, ty, kind: Box::new(kind) },
-                        };
+                for end in &[lo, hi] {
+                    if let Some((_, Some(ascription))) = end {
+                        let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
+                        kind = PatKind::AscribeUserType { ascription: *ascription, subpattern };
                     }
                 }
 
@@ -747,6 +765,7 @@
                     self.param_env.with_reveal_all(),
                     def_id,
                     substs,
+                    None,
                     Some(span),
                 ) {
                     Ok(value) => {
@@ -801,40 +820,35 @@
     /// which would overflow if we tried to evaluate `128_i8` and then negate
     /// afterwards.
     fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
-        match expr.kind {
-            hir::ExprKind::Lit(ref lit) => {
-                let ty = self.tables.expr_ty(expr);
-                match lit_to_const(&lit.node, self.tcx, ty, false) {
-                    Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span).kind,
-                    Err(LitToConstError::UnparseableFloat) => {
-                        self.errors.push(PatternError::FloatBug);
-                        PatKind::Wild
-                    }
-                    Err(LitToConstError::Reported) => PatKind::Wild,
+        if let hir::ExprKind::Path(ref qpath) = expr.kind {
+            *self.lower_path(qpath, expr.hir_id, expr.span).kind
+        } else {
+            let (lit, neg) = match expr.kind {
+                hir::ExprKind::Lit(ref lit) => (lit, false),
+                hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => {
+                    let lit = match expr.kind {
+                        hir::ExprKind::Lit(ref lit) => lit,
+                        _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+                    };
+                    (lit, true)
                 }
-            }
-            hir::ExprKind::Path(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
-            hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => {
-                let ty = self.tables.expr_ty(expr);
-                let lit = match expr.kind {
-                    hir::ExprKind::Lit(ref lit) => lit,
-                    _ => span_bug!(expr.span, "not a literal: {:?}", expr),
-                };
-                match lit_to_const(&lit.node, self.tcx, ty, true) {
-                    Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span).kind,
-                    Err(LitToConstError::UnparseableFloat) => {
-                        self.errors.push(PatternError::FloatBug);
-                        PatKind::Wild
-                    }
-                    Err(LitToConstError::Reported) => PatKind::Wild,
+                _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+            };
+
+            let lit_input = LitToConstInput { lit: &lit.node, ty: self.tables.expr_ty(expr), neg };
+            match self.tcx.at(expr.span).lit_to_const(lit_input) {
+                Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span).kind,
+                Err(LitToConstError::UnparseableFloat) => {
+                    self.errors.push(PatternError::FloatBug);
+                    PatKind::Wild
                 }
+                Err(LitToConstError::Reported) => PatKind::Wild,
             }
-            _ => span_bug!(expr.span, "not a literal: {:?}", expr),
         }
     }
 }
 
-impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
+impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -844,7 +858,7 @@
     }
 }
 
-pub trait PatternFoldable<'tcx>: Sized {
+crate trait PatternFoldable<'tcx>: Sized {
     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.super_fold_with(folder)
     }
@@ -852,7 +866,7 @@
     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
 }
 
-pub trait PatternFolder<'tcx>: Sized {
+crate trait PatternFolder<'tcx>: Sized {
     fn fold_pattern(&mut self, pattern: &Pat<'tcx>) -> Pat<'tcx> {
         pattern.super_fold_with(self)
     }
@@ -980,7 +994,7 @@
     }
 }
 
-pub fn compare_const_vals<'tcx>(
+crate fn compare_const_vals<'tcx>(
     tcx: TyCtxt<'tcx>,
     a: &'tcx ty::Const<'tcx>,
     b: &'tcx ty::Const<'tcx>,
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir_build/hair/util.rs
similarity index 100%
rename from src/librustc_mir/hair/util.rs
rename to src/librustc_mir_build/hair/util.rs
diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs
new file mode 100644
index 0000000..42292d6
--- /dev/null
+++ b/src/librustc_mir_build/lib.rs
@@ -0,0 +1,27 @@
+//! Construction of MIR from HIR.
+//!
+//! This crate also contains the match exhaustiveness and usefulness checking.
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
+#![feature(bool_to_option)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate rustc;
+
+mod build;
+mod hair;
+mod lints;
+
+use rustc::ty::query::Providers;
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.check_match = hair::pattern::check_match;
+    providers.lit_to_const = hair::constant::lit_to_const;
+    providers.mir_built = build::mir_built;
+}
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir_build/lints.rs
similarity index 96%
rename from src/librustc_mir/lints.rs
rename to src/librustc_mir_build/lints.rs
index fc7f2eb..4244e1b 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir_build/lints.rs
@@ -1,13 +1,13 @@
-use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc::mir::{self, Body, TerminatorKind};
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::FnKind;
 use rustc_index::bit_set::BitSet;
 
-pub fn check(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
+crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
@@ -15,7 +15,7 @@
     }
 }
 
-fn check_fn_for_unconditional_recursion(
+fn check_fn_for_unconditional_recursion<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_kind: FnKind<'_>,
     body: &Body<'tcx>,
diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml
deleted file mode 100644
index bda4078..0000000
--- a/src/librustc_msan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_msan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_msan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
deleted file mode 100644
index dc08d51..0000000
--- a/src/librustc_msan/build.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-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();
-
-        let (native, target) = match sanitizer_lib_boilerplate("msan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_msan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index d41d899..8071bc6 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -16,8 +16,8 @@
 rustc_feature = { path = "../librustc_feature" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 syntax = { path = "../libsyntax" }
 unicode-normalization = "0.1.11"
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index f2ffd94..bf696fa 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -9,18 +9,21 @@
 //! [#64197]: https://github.com/rust-lang/rust/issues/64197
 
 use crate::{parse_in, validate_attr};
-use rustc_errors::Applicability;
-use rustc_feature::Features;
-use rustc_span::edition::Edition;
-use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
+use rustc_feature::{Feature, Features, State as FeatureState};
+use rustc_feature::{
+    ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
+};
+use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, AttrItem, Attribute, MetaItem};
 use syntax::attr;
 use syntax::attr::HasAttrs;
-use syntax::feature_gate::{feature_err, get_features};
 use syntax::mut_visit::*;
 use syntax::ptr::P;
-use syntax::sess::ParseSess;
+use syntax::sess::{feature_err, ParseSess};
 use syntax::util::map_in_place::MapInPlace;
 
 use smallvec::SmallVec;
@@ -31,6 +34,172 @@
     pub features: Option<&'a Features>,
 }
 
+fn get_features(
+    span_handler: &Handler,
+    krate_attrs: &[ast::Attribute],
+    crate_edition: Edition,
+    allow_features: &Option<Vec<String>>,
+) -> Features {
+    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
+        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
+        err.span_label(span, "feature has been removed");
+        if let Some(reason) = reason {
+            err.note(reason);
+        }
+        err.emit();
+    }
+
+    fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
+        ACTIVE_FEATURES.iter().filter(move |feature| {
+            if let Some(feature_edition) = feature.edition {
+                feature_edition <= edition
+            } else {
+                false
+            }
+        })
+    }
+
+    let mut features = Features::default();
+    let mut edition_enabled_features = FxHashMap::default();
+
+    for &edition in ALL_EDITIONS {
+        if edition <= crate_edition {
+            // The `crate_edition` implies its respective umbrella feature-gate
+            // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
+            edition_enabled_features.insert(edition.feature_name(), edition);
+        }
+    }
+
+    for feature in active_features_up_to(crate_edition) {
+        feature.set(&mut features, DUMMY_SP);
+        edition_enabled_features.insert(feature.name, crate_edition);
+    }
+
+    // Process the edition umbrella feature-gates first, to ensure
+    // `edition_enabled_features` is completed before it's queried.
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        for mi in list {
+            if !mi.is_word() {
+                continue;
+            }
+
+            let name = mi.name_or_empty();
+
+            let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
+            if let Some(edition) = edition {
+                if edition <= crate_edition {
+                    continue;
+                }
+
+                for feature in active_features_up_to(edition) {
+                    // FIXME(Manishearth) there is currently no way to set
+                    // lib features by edition
+                    feature.set(&mut features, DUMMY_SP);
+                    edition_enabled_features.insert(feature.name, edition);
+                }
+            }
+        }
+    }
+
+    for attr in krate_attrs {
+        if !attr.check_name(sym::feature) {
+            continue;
+        }
+
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => continue,
+        };
+
+        let bad_input = |span| {
+            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
+        };
+
+        for mi in list {
+            let name = match mi.ident() {
+                Some(ident) if mi.is_word() => ident.name,
+                Some(ident) => {
+                    bad_input(mi.span())
+                        .span_suggestion(
+                            mi.span(),
+                            "expected just one word",
+                            format!("{}", ident.name),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    continue;
+                }
+                None => {
+                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+                    continue;
+                }
+            };
+
+            if let Some(edition) = edition_enabled_features.get(&name) {
+                let msg =
+                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
+                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+                continue;
+            }
+
+            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
+                // Handled in the separate loop above.
+                continue;
+            }
+
+            let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
+            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
+            if let Some(Feature { state, .. }) = removed.or(stable_removed) {
+                if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
+                    state
+                {
+                    feature_removed(span_handler, mi.span(), *reason);
+                    continue;
+                }
+            }
+
+            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
+                let since = Some(Symbol::intern(since));
+                features.declared_lang_features.push((name, mi.span(), since));
+                continue;
+            }
+
+            if let Some(allowed) = allow_features.as_ref() {
+                if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
+                    struct_span_err!(
+                        span_handler,
+                        mi.span(),
+                        E0725,
+                        "the feature `{}` is not in the list of allowed features",
+                        name
+                    )
+                    .emit();
+                    continue;
+                }
+            }
+
+            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
+                f.set(&mut features, mi.span());
+                features.declared_lang_features.push((name, mi.span(), None));
+                continue;
+            }
+
+            features.declared_lib_features.push((name, mi.span()));
+        }
+    }
+
+    features
+}
+
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
 pub fn features(
     mut krate: ast::Crate,
diff --git a/src/librustc_parse/lexer/unescape_error_reporting.rs b/src/librustc_parse/lexer/unescape_error_reporting.rs
index 151c63a..88762da 100644
--- a/src/librustc_parse/lexer/unescape_error_reporting.rs
+++ b/src/librustc_parse/lexer/unescape_error_reporting.rs
@@ -3,11 +3,10 @@
 use std::iter::once;
 use std::ops::Range;
 
+use rustc_errors::{Applicability, Handler};
 use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
 
-use syntax::errors::{Applicability, Handler};
-
 pub(crate) fn emit_unescape_error(
     handler: &Handler,
     // interior part of the literal, without quotes
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 9227e96..08f4f21 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -2,7 +2,7 @@
 
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 use syntax::ast;
 use syntax::print::pprust;
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index 81f31b2..3d40b91 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -236,8 +236,8 @@
             self.struct_span_err(lit.span, msg)
                 .help(
                     "instead of using a suffixed literal \
-                                    (1u8, 1.0f32, etc.), use an unsuffixed version \
-                                    (1, 1.0, etc.).",
+                                    (`1u8`, `1.0f32`, etc.), use an unsuffixed version \
+                                    (`1`, `1.0`, etc.)",
                 )
                 .emit()
         }
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 94785e9..80bc5c1 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1,8 +1,9 @@
 use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_error_codes::*;
-use rustc_errors::{self, pluralize, Applicability, DiagnosticBuilder, Handler, PResult};
+use rustc_errors::{pluralize, struct_span_err};
+use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult};
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
 use syntax::ast::{
@@ -11,7 +12,6 @@
 use syntax::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token::{self, token_can_begin_expr, TokenKind};
 use syntax::util::parser::AssocOp;
 
@@ -51,7 +51,6 @@
         secondary_path: String,
     },
     UselessDocComment,
-    InclusiveRangeWithNoEnd,
 }
 
 impl Error {
@@ -102,11 +101,6 @@
                 );
                 err
             }
-            Error::InclusiveRangeWithNoEnd => {
-                let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end",);
-                err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
-                err
-            }
         }
     }
 }
@@ -265,10 +259,7 @@
             };
             (
                 format!("expected one of {}, found {}", expect, actual),
-                (
-                    self.sess.source_map().next_point(self.prev_span),
-                    format!("expected one of {}", short_expect),
-                ),
+                (self.prev_span.shrink_to_hi(), format!("expected one of {}", short_expect)),
             )
         } else if expected.is_empty() {
             (
@@ -278,7 +269,7 @@
         } else {
             (
                 format!("expected {}, found {}", expect, actual),
-                (self.sess.source_map().next_point(self.prev_span), format!("expected {}", expect)),
+                (self.prev_span.shrink_to_hi(), format!("expected {}", expect)),
             )
         };
         self.last_unexpected_token_span = Some(self.token.span);
@@ -500,6 +491,58 @@
         }
     }
 
+    /// Check to see if a pair of chained operators looks like an attempt at chained comparison,
+    /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
+    /// parenthesising the leftmost comparison.
+    fn attempt_chained_comparison_suggestion(
+        &mut self,
+        err: &mut DiagnosticBuilder<'_>,
+        inner_op: &Expr,
+        outer_op: &Spanned<AssocOp>,
+    ) {
+        if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
+            match (op.node, &outer_op.node) {
+                // `x < y < z` and friends.
+                (BinOpKind::Lt, AssocOp::Less) | (BinOpKind::Lt, AssocOp::LessEqual) |
+                (BinOpKind::Le, AssocOp::LessEqual) | (BinOpKind::Le, AssocOp::Less) |
+                // `x > y > z` and friends.
+                (BinOpKind::Gt, AssocOp::Greater) | (BinOpKind::Gt, AssocOp::GreaterEqual) |
+                (BinOpKind::Ge, AssocOp::GreaterEqual) | (BinOpKind::Ge, AssocOp::Greater) => {
+                    let expr_to_str = |e: &Expr| {
+                        self.span_to_snippet(e.span)
+                            .unwrap_or_else(|_| pprust::expr_to_string(&e))
+                    };
+                    err.span_suggestion(
+                        inner_op.span.to(outer_op.span),
+                        "split the comparison into two...",
+                        format!(
+                            "{} {} {} && {} {}",
+                            expr_to_str(&l1),
+                            op.node.to_string(),
+                            expr_to_str(&r1),
+                            expr_to_str(&r1),
+                            outer_op.node.to_ast_binop().unwrap().to_string(),
+                        ),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.span_suggestion(
+                        inner_op.span.to(outer_op.span),
+                        "...or parenthesize one of the comparisons",
+                        format!(
+                            "({} {} {}) {}",
+                            expr_to_str(&l1),
+                            op.node.to_string(),
+                            expr_to_str(&r1),
+                            outer_op.node.to_ast_binop().unwrap().to_string(),
+                        ),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                _ => {}
+            }
+        }
+    }
+
     /// 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 (see `fn precedence`) and are left-associative (see `fn fixity`).
@@ -515,27 +558,31 @@
     ///           /   \
     ///     inner_op   r2
     ///        /  \
-    ///     l1    r1
+    ///      l1    r1
     pub(super) fn check_no_chained_comparison(
         &mut self,
-        lhs: &Expr,
-        outer_op: &AssocOp,
+        inner_op: &Expr,
+        outer_op: &Spanned<AssocOp>,
     ) -> PResult<'a, Option<P<Expr>>> {
         debug_assert!(
-            outer_op.is_comparison(),
+            outer_op.node.is_comparison(),
             "check_no_chained_comparison: {:?} is not comparison",
-            outer_op,
+            outer_op.node,
         );
 
         let mk_err_expr =
             |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new())));
 
-        match lhs.kind {
+        match inner_op.kind {
             ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
                 // Respan to include both operators.
                 let op_span = op.span.to(self.prev_span);
-                let mut err = self
-                    .struct_span_err(op_span, "chained comparison operators require parentheses");
+                let mut err =
+                    self.struct_span_err(op_span, "comparison operators cannot be chained");
+
+                // If it looks like a genuine attempt to chain operators (as opposed to a
+                // misformatted turbofish, for instance), suggest a correct form.
+                self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
 
                 let suggest = |err: &mut DiagnosticBuilder<'_>| {
                     err.span_suggestion_verbose(
@@ -547,12 +594,12 @@
                 };
 
                 if op.node == BinOpKind::Lt &&
-                    *outer_op == AssocOp::Less ||  // Include `<` to provide this recommendation
-                    *outer_op == AssocOp::Greater
+                    outer_op.node == AssocOp::Less ||  // Include `<` to provide this recommendation
+                    outer_op.node == AssocOp::Greater
                 // even in a case like the following:
                 {
                     //     Foo<Bar<Baz<Qux, ()>>>
-                    if *outer_op == AssocOp::Less {
+                    if outer_op.node == AssocOp::Less {
                         let snapshot = self.clone();
                         self.bump();
                         // So far we have parsed `foo<bar<`, consume the rest of the type args.
@@ -584,7 +631,7 @@
                                 // FIXME: actually check that the two expressions in the binop are
                                 // paths and resynthesize new fn call expression instead of using
                                 // `ExprKind::Err` placeholder.
-                                mk_err_expr(self, lhs.span.to(self.prev_span))
+                                mk_err_expr(self, inner_op.span.to(self.prev_span))
                             }
                             Err(mut expr_err) => {
                                 expr_err.cancel();
@@ -606,7 +653,7 @@
                                 // FIXME: actually check that the two expressions in the binop are
                                 // paths and resynthesize new fn call expression instead of using
                                 // `ExprKind::Err` placeholder.
-                                mk_err_expr(self, lhs.span.to(self.prev_span))
+                                mk_err_expr(self, inner_op.span.to(self.prev_span))
                             }
                         }
                     } else {
@@ -809,7 +856,7 @@
             _ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span),
             // EOF, don't want to point at the following char, but rather the last token.
             (token::Eof, None) => (self.prev_span, self.token.span),
-            _ => (self.sess.source_map().next_point(self.prev_span), self.token.span),
+            _ => (self.prev_span.shrink_to_hi(), self.token.span),
         };
         let msg = format!(
             "expected `{}`, found {}",
@@ -1132,7 +1179,7 @@
                     err.span_label(sp, "unclosed delimiter");
                 }
                 err.span_suggestion_short(
-                    self.sess.source_map().next_point(self.prev_span),
+                    self.prev_span.shrink_to_hi(),
                     &format!("{} may belong here", delim.to_string()),
                     delim.to_string(),
                     Applicability::MaybeIncorrect,
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 90f1537..098c835 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1,11 +1,10 @@
-use super::diagnostics::Error;
 use super::pat::{GateOr, PARAM_EXPECTED};
 use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
 use rustc_errors::{Applicability, PResult};
-use rustc_span::source_map::{self, Span};
+use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::mem;
 use syntax::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, DUMMY_NODE_ID};
@@ -181,17 +180,17 @@
             };
 
             let cur_op_span = self.token.span;
-            let restrictions = if op.is_assign_like() {
+            let restrictions = if op.node.is_assign_like() {
                 self.restrictions & Restrictions::NO_STRUCT_LITERAL
             } else {
                 self.restrictions
             };
-            let prec = op.precedence();
+            let prec = op.node.precedence();
             if prec < min_prec {
                 break;
             }
             // Check for deprecated `...` syntax
-            if self.token == token::DotDotDot && op == AssocOp::DotDotEq {
+            if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq {
                 self.err_dotdotdot_syntax(self.token.span);
             }
 
@@ -200,11 +199,12 @@
             }
 
             self.bump();
-            if op.is_comparison() {
+            if op.node.is_comparison() {
                 if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
                     return Ok(expr);
                 }
             }
+            let op = op.node;
             // Special cases:
             if op == AssocOp::As {
                 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
@@ -298,7 +298,7 @@
     }
 
     fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
-        match (self.expr_is_complete(lhs), self.check_assoc_op()) {
+        match (self.expr_is_complete(lhs), self.check_assoc_op().map(|op| op.node)) {
             // Semi-statement forms are odd:
             // See https://github.com/rust-lang/rust/issues/29071
             (true, None) => false,
@@ -343,19 +343,22 @@
     /// The method does not advance the current token.
     ///
     /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
-    fn check_assoc_op(&self) -> Option<AssocOp> {
-        match (AssocOp::from_token(&self.token), &self.token.kind) {
-            (op @ Some(_), _) => op,
-            (None, token::Ident(sym::and, false)) => {
-                self.error_bad_logical_op("and", "&&", "conjunction");
-                Some(AssocOp::LAnd)
-            }
-            (None, token::Ident(sym::or, false)) => {
-                self.error_bad_logical_op("or", "||", "disjunction");
-                Some(AssocOp::LOr)
-            }
-            _ => None,
-        }
+    fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
+        Some(Spanned {
+            node: match (AssocOp::from_token(&self.token), &self.token.kind) {
+                (Some(op), _) => op,
+                (None, token::Ident(sym::and, false)) => {
+                    self.error_bad_logical_op("and", "&&", "conjunction");
+                    AssocOp::LAnd
+                }
+                (None, token::Ident(sym::or, false)) => {
+                    self.error_bad_logical_op("or", "||", "disjunction");
+                    AssocOp::LOr
+                }
+                _ => return None,
+            },
+            span: self.token.span,
+        })
     }
 
     /// Error on `and` and `or` suggesting `&&` and `||` respectively.
@@ -1646,7 +1649,7 @@
                             //   |      |
                             //   |      parsed until here as `"y" & X`
                             err.span_suggestion_short(
-                                cm.next_point(arm_start_span),
+                                arm_start_span.shrink_to_hi(),
                                 "missing a comma here to end this `match` arm",
                                 ",".to_owned(),
                                 Applicability::MachineApplicable,
@@ -1967,7 +1970,8 @@
         limits: RangeLimits,
     ) -> PResult<'a, ExprKind> {
         if end.is_none() && limits == RangeLimits::Closed {
-            Err(self.span_fatal_err(self.token.span, Error::InclusiveRangeWithNoEnd))
+            self.error_inclusive_range_with_no_end(self.prev_span);
+            Ok(ExprKind::Err)
         } else {
             Ok(ExprKind::Range(start, end, limits))
         }
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index 1b816e2..0755837 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -156,7 +156,7 @@
             self.expect_gt()?;
             (params, span_lo.to(self.prev_span))
         } else {
-            (vec![], self.prev_span.between(self.token.span))
+            (vec![], self.prev_span.shrink_to_hi())
         };
         Ok(ast::Generics {
             params,
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index a05bc48..31db7fc 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -3,8 +3,7 @@
 
 use crate::maybe_whole;
 
-use rustc_error_codes::*;
-use rustc_errors::{Applicability, DiagnosticBuilder, PResult, StashKey};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey};
 use rustc_span::source_map::{self, respan, Span};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::BytePos;
@@ -16,7 +15,6 @@
 use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token;
 use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
 
@@ -141,7 +139,7 @@
                     self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span));
                 }
                 let ext = self.parse_extern()?;
-                self.bump(); // `fn`
+                self.expect_keyword(kw::Fn)?;
 
                 let header = FnHeader {
                     unsafety,
@@ -543,10 +541,11 @@
     ///    impl<'a, T> TYPE { /* impl items */ }
     ///    impl<'a, T> TRAIT for TYPE { /* impl items */ }
     ///    impl<'a, T> !TRAIT for TYPE { /* impl items */ }
+    ///    impl<'a, T> const TRAIT for TYPE { /* impl items */ }
     ///
     /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
-    ///     `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
-    ///     `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
+    ///   `impl` GENERICS `const`? `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
+    ///   `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
     fn parse_item_impl(
         &mut self,
         unsafety: Unsafety,
@@ -556,7 +555,19 @@
         let mut generics = if self.choose_generics_over_qpath() {
             self.parse_generics()?
         } else {
-            Generics::default()
+            let mut generics = Generics::default();
+            // impl A for B {}
+            //    /\ this is where `generics.span` should point when there are no type params.
+            generics.span = self.prev_span.shrink_to_hi();
+            generics
+        };
+
+        let constness = if self.eat_keyword(kw::Const) {
+            let span = self.prev_span;
+            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+            Constness::Const
+        } else {
+            Constness::NotConst
         };
 
         // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
@@ -621,27 +632,29 @@
                 };
                 let trait_ref = TraitRef { path, ref_id: ty_first.id };
 
-                ItemKind::Impl(
+                ItemKind::Impl {
                     unsafety,
                     polarity,
                     defaultness,
+                    constness,
                     generics,
-                    Some(trait_ref),
-                    ty_second,
-                    impl_items,
-                )
+                    of_trait: Some(trait_ref),
+                    self_ty: ty_second,
+                    items: impl_items,
+                }
             }
             None => {
                 // impl Type
-                ItemKind::Impl(
+                ItemKind::Impl {
                     unsafety,
                     polarity,
                     defaultness,
+                    constness,
                     generics,
-                    None,
-                    ty_first,
-                    impl_items,
-                )
+                    of_trait: None,
+                    self_ty: ty_first,
+                    items: impl_items,
+                }
             }
         };
 
@@ -1490,7 +1503,7 @@
                 }
             }
             _ => {
-                let sp = self.sess.source_map().next_point(self.prev_span);
+                let sp = self.prev_span.shrink_to_hi();
                 let mut err = self.struct_span_err(
                     sp,
                     &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)),
@@ -1629,7 +1642,7 @@
             // it's safe to peel off one character only when it has the close delim
             self.prev_span.with_lo(self.prev_span.hi() - BytePos(1))
         } else {
-            self.sess.source_map().next_point(self.prev_span)
+            self.prev_span.shrink_to_hi()
         };
 
         self.struct_span_err(
@@ -1645,7 +1658,7 @@
             Applicability::MaybeIncorrect,
         )
         .span_suggestion(
-            self.sess.source_map().next_point(self.prev_span),
+            self.prev_span.shrink_to_hi(),
             "add a semicolon",
             ';'.to_string(),
             Applicability::MaybeIncorrect,
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index a2fa335..4a90163 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -2,6 +2,7 @@
 mod expr;
 mod item;
 mod module;
+pub use module::{ModulePath, ModulePathSuccess};
 mod pat;
 mod path;
 mod ty;
@@ -15,7 +16,7 @@
 use crate::{Directory, DirectoryOwnership};
 
 use log::debug;
-use rustc_errors::{Applicability, DiagnosticBuilder, FatalError, PResult};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
@@ -24,7 +25,6 @@
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::sess::ParseSess;
-use syntax::struct_span_err;
 use syntax::token::{self, DelimToken, Token, TokenKind};
 use syntax::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndJoint};
 use syntax::util::comments::{doc_comment_style, strip_doc_comment_decoration};
@@ -33,8 +33,6 @@
 use std::path::PathBuf;
 use std::{cmp, mem, slice};
 
-use rustc_error_codes::*;
-
 bitflags::bitflags! {
     struct Restrictions: u8 {
         const STMT_EXPR         = 1 << 0;
@@ -118,7 +116,8 @@
     /// Used to determine the path to externally loaded source files.
     pub(super) directory: Directory<'a>,
     /// `true` to parse sub-modules in other files.
-    pub(super) recurse_into_file_modules: bool,
+    // Public for rustfmt usage.
+    pub recurse_into_file_modules: bool,
     /// Name of the root module this parser originated from. If `None`, then the
     /// name is not known. This does not change while the parser is descending
     /// into modules, and sub-parsers have new values for this name.
@@ -127,7 +126,8 @@
     token_cursor: TokenCursor,
     desugar_doc_comments: bool,
     /// `true` we should configure out of line modules as we parse.
-    cfg_mods: bool,
+    // Public for rustfmt usage.
+    pub cfg_mods: bool,
     /// This field is used to keep track of how many left angle brackets we have seen. This is
     /// required in order to detect extra leading left angle brackets (`<` characters) and error
     /// appropriately.
@@ -484,7 +484,8 @@
         }
     }
 
-    fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
+    // Public for rustfmt usage.
+    pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
         self.parse_ident_common(true)
     }
 
@@ -541,7 +542,8 @@
 
     /// If the next token is the given keyword, eats it and returns `true`.
     /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
-    fn eat_keyword(&mut self, kw: Symbol) -> bool {
+    // Public for rustfmt usage.
+    pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
         if self.check_keyword(kw) {
             self.bump();
             true
@@ -766,7 +768,7 @@
                             break;
                         }
                         Err(mut expect_err) => {
-                            let sp = self.sess.source_map().next_point(self.prev_span);
+                            let sp = self.prev_span.shrink_to_hi();
                             let token_str = pprust::token_kind_to_string(t);
 
                             // Attempt to keep parsing if it was a similar separator.
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
index 3254ab5..6ce94d3 100644
--- a/src/librustc_parse/parser/module.rs
+++ b/src/librustc_parse/parser/module.rs
@@ -14,13 +14,15 @@
 use std::path::{self, Path, PathBuf};
 
 /// Information about the path to a module.
-pub(super) struct ModulePath {
+// Public for rustfmt usage.
+pub struct ModulePath {
     name: String,
     path_exists: bool,
     pub result: Result<ModulePathSuccess, Error>,
 }
 
-pub(super) struct ModulePathSuccess {
+// Public for rustfmt usage.
+pub struct ModulePathSuccess {
     pub path: PathBuf,
     pub directory_ownership: DirectoryOwnership,
 }
@@ -177,7 +179,8 @@
         }
     }
 
-    pub(super) fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
+    // Public for rustfmt usage.
+    pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
         if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) {
             let s = s.as_str();
 
@@ -194,7 +197,8 @@
     }
 
     /// Returns a path to a module.
-    pub(super) fn default_submod_path(
+    // Public for rustfmt usage.
+    pub fn default_submod_path(
         id: ast::Ident,
         relative: Option<ast::Ident>,
         dir_path: &Path,
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index bf7f573..edb9044 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,6 +1,6 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym};
 use syntax::ast::{self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax};
@@ -209,13 +209,13 @@
         if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
             err.span_suggestion(
                 seq_span,
-                "try adding parentheses to match on a tuple..",
+                "try adding parentheses to match on a tuple...",
                 format!("({})", seq_snippet),
                 Applicability::MachineApplicable,
             )
             .span_suggestion(
                 seq_span,
-                "..or a vertical bar to match on multiple alternatives",
+                "...or a vertical bar to match on multiple alternatives",
                 format!("{}", seq_snippet.replace(",", " |")),
                 Applicability::MachineApplicable,
             );
@@ -281,91 +281,73 @@
         maybe_whole!(self, NtPat, |x| x);
 
         let lo = self.token.span;
-        let pat = match self.token.kind {
-            token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?,
-            token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?,
-            token::OpenDelim(token::Bracket) => {
-                // Parse `[pat, pat,...]` as a slice pattern.
-                let (pats, _) =
-                    self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
-                PatKind::Slice(pats)
+
+        let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
+            self.parse_pat_deref(expected)?
+        } else if self.check(&token::OpenDelim(token::Paren)) {
+            self.parse_pat_tuple_or_parens()?
+        } else if self.check(&token::OpenDelim(token::Bracket)) {
+            // Parse `[pat, pat,...]` as a slice pattern.
+            let (pats, _) =
+                self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
+            PatKind::Slice(pats)
+        } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
+            // A rest pattern `..`.
+            self.bump(); // `..`
+            PatKind::Rest
+        } else if let Some(form) = self.parse_range_end() {
+            self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
+        } else if self.eat_keyword(kw::Underscore) {
+            // Parse _
+            PatKind::Wild
+        } else if self.eat_keyword(kw::Mut) {
+            self.parse_pat_ident_mut()?
+        } else if self.eat_keyword(kw::Ref) {
+            // Parse ref ident @ pat / ref mut ident @ pat
+            let mutbl = self.parse_mutability();
+            self.parse_pat_ident(BindingMode::ByRef(mutbl))?
+        } else if self.eat_keyword(kw::Box) {
+            // Parse `box pat`
+            let pat = self.parse_pat_with_range_pat(false, None)?;
+            self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
+            PatKind::Box(pat)
+        } else if self.can_be_ident_pat() {
+            // Parse `ident @ pat`
+            // This can give false positives and parse nullary enums,
+            // they are dealt with later in resolve.
+            self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
+        } else if self.is_start_of_pat_with_path() {
+            // Parse pattern starting with a path
+            let (qself, path) = if self.eat_lt() {
+                // Parse a qualified path
+                let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+                (Some(qself), path)
+            } else {
+                // Parse an unqualified path
+                (None, self.parse_path(PathStyle::Expr)?)
+            };
+            let span = lo.to(self.prev_span);
+
+            if qself.is_none() && self.check(&token::Not) {
+                self.parse_pat_mac_invoc(path)?
+            } else if let Some(form) = self.parse_range_end() {
+                let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
+                self.parse_pat_range_begin_with(begin, form)?
+            } else if self.check(&token::OpenDelim(token::Brace)) {
+                self.parse_pat_struct(qself, path)?
+            } else if self.check(&token::OpenDelim(token::Paren)) {
+                self.parse_pat_tuple_struct(qself, path)?
+            } else {
+                PatKind::Path(qself, path)
             }
-            token::DotDot => {
-                self.bump();
-                if self.is_pat_range_end_start() {
-                    // Parse `..42` for recovery.
-                    self.parse_pat_range_to(RangeEnd::Excluded, "..")?
-                } else {
-                    // A rest pattern `..`.
-                    PatKind::Rest
-                }
-            }
-            token::DotDotEq => {
-                // Parse `..=42` for recovery.
-                self.bump();
-                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?
-            }
-            token::DotDotDot => {
-                // Parse `...42` for recovery.
-                self.bump();
-                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?
-            }
-            // At this point, token != `&`, `&&`, `(`, `[`, `..`, `..=`, or `...`.
-            _ => {
-                if self.eat_keyword(kw::Underscore) {
-                    // Parse _
-                    PatKind::Wild
-                } else if self.eat_keyword(kw::Mut) {
-                    self.parse_pat_ident_mut()?
-                } else if self.eat_keyword(kw::Ref) {
-                    // Parse ref ident @ pat / ref mut ident @ pat
-                    let mutbl = self.parse_mutability();
-                    self.parse_pat_ident(BindingMode::ByRef(mutbl))?
-                } else if self.eat_keyword(kw::Box) {
-                    // Parse `box pat`
-                    let pat = self.parse_pat_with_range_pat(false, None)?;
-                    self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
-                    PatKind::Box(pat)
-                } else if self.can_be_ident_pat() {
-                    // Parse `ident @ pat`
-                    // This can give false positives and parse nullary enums,
-                    // they are dealt with later in resolve.
-                    self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
-                } else if self.is_start_of_pat_with_path() {
-                    // Parse pattern starting with a path
-                    let (qself, path) = if self.eat_lt() {
-                        // Parse a qualified path
-                        let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
-                        (Some(qself), path)
-                    } else {
-                        // Parse an unqualified path
-                        (None, self.parse_path(PathStyle::Expr)?)
-                    };
-                    match self.token.kind {
-                        token::Not if qself.is_none() => self.parse_pat_mac_invoc(path)?,
-                        token::DotDotDot | token::DotDotEq | token::DotDot => {
-                            self.parse_pat_range_starting_with_path(lo, qself, path)?
-                        }
-                        token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
-                        token::OpenDelim(token::Paren) => {
-                            self.parse_pat_tuple_struct(qself, path)?
-                        }
-                        _ => PatKind::Path(qself, path),
-                    }
-                } else {
-                    // Try to parse everything else as literal with optional minus
-                    match self.parse_literal_maybe_minus() {
-                        Ok(begin)
-                            if self.check(&token::DotDot)
-                                || self.check(&token::DotDotEq)
-                                || self.check(&token::DotDotDot) =>
-                        {
-                            self.parse_pat_range_starting_with_lit(begin)?
-                        }
-                        Ok(begin) => PatKind::Lit(begin),
-                        Err(err) => return self.fatal_unexpected_non_pat(err, expected),
-                    }
-                }
+        } else {
+            // Try to parse everything else as literal with optional minus
+            match self.parse_literal_maybe_minus() {
+                Ok(begin) => match self.parse_range_end() {
+                    Some(form) => self.parse_pat_range_begin_with(begin, form)?,
+                    None => PatKind::Lit(begin),
+                },
+                Err(err) => return self.fatal_unexpected_non_pat(err, expected),
             }
         };
 
@@ -374,7 +356,7 @@
         let pat = self.recover_intersection_pat(pat)?;
 
         if !allow_range_pat {
-            self.ban_pat_range_if_ambiguous(&pat)?
+            self.ban_pat_range_if_ambiguous(&pat)
         }
 
         Ok(pat)
@@ -441,26 +423,25 @@
     }
 
     /// Ban a range pattern if it has an ambiguous interpretation.
-    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
+    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) {
         match pat.kind {
             PatKind::Range(
                 ..,
                 Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. },
-            ) => return Ok(()),
+            ) => return,
             PatKind::Range(..) => {}
-            _ => return Ok(()),
+            _ => return,
         }
 
-        let mut err =
-            self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation");
-        err.span_suggestion(
-            pat.span,
-            "add parentheses to clarify the precedence",
-            format!("({})", pprust::pat_to_string(&pat)),
-            // "ambiguous interpretation" implies that we have to be guessing
-            Applicability::MaybeIncorrect,
-        );
-        Err(err)
+        self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation")
+            .span_suggestion(
+                pat.span,
+                "add parentheses to clarify the precedence",
+                format!("({})", pprust::pat_to_string(&pat)),
+                // "ambiguous interpretation" implies that we have to be guessing
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
     }
 
     /// Parse `&pat` / `&mut pat`.
@@ -618,51 +599,6 @@
         Ok(PatKind::Mac(mac))
     }
 
-    fn excluded_range_end(&self, span: Span) -> RangeEnd {
-        self.sess.gated_spans.gate(sym::exclusive_range_pattern, span);
-        RangeEnd::Excluded
-    }
-
-    /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
-    /// The `$path` has already been parsed and the next token is the `$form`.
-    fn parse_pat_range_starting_with_path(
-        &mut self,
-        lo: Span,
-        qself: Option<QSelf>,
-        path: Path,
-    ) -> PResult<'a, PatKind> {
-        let (end_kind, form) = match self.token.kind {
-            token::DotDot => (self.excluded_range_end(self.token.span), ".."),
-            token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
-            token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
-            _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
-        };
-        let op_span = self.token.span;
-        // Parse range
-        let span = lo.to(self.prev_span);
-        let begin = self.mk_expr(span, ExprKind::Path(qself, path), AttrVec::new());
-        self.bump();
-        let end = self.parse_pat_range_end_opt(&begin, form)?;
-        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
-    }
-
-    /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`.
-    /// The `$path` has already been parsed and the next token is the `$form`.
-    fn parse_pat_range_starting_with_lit(&mut self, begin: P<Expr>) -> PResult<'a, PatKind> {
-        let op_span = self.token.span;
-        let (end_kind, form) = if self.eat(&token::DotDotDot) {
-            (RangeEnd::Included(RangeSyntax::DotDotDot), "...")
-        } else if self.eat(&token::DotDotEq) {
-            (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
-        } else if self.eat(&token::DotDot) {
-            (self.excluded_range_end(op_span), "..")
-        } else {
-            panic!("impossible case: we already matched on a range-operator token")
-        };
-        let end = self.parse_pat_range_end_opt(&begin, form)?;
-        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
-    }
-
     fn fatal_unexpected_non_pat(
         &mut self,
         mut err: DiagnosticBuilder<'a>,
@@ -684,57 +620,85 @@
         Err(err)
     }
 
-    /// Is the current token suitable as the start of a range patterns end?
-    fn is_pat_range_end_start(&self) -> bool {
-        self.token.is_path_start() // e.g. `MY_CONST`;
-            || self.token == token::Dot // e.g. `.5` for recovery;
-            || self.token.can_begin_literal_or_bool() // e.g. `42`.
-            || self.token.is_whole_expr()
+    /// Parses the range pattern end form `".." | "..." | "..=" ;`.
+    fn parse_range_end(&mut self) -> Option<Spanned<RangeEnd>> {
+        let re = if self.eat(&token::DotDotDot) {
+            RangeEnd::Included(RangeSyntax::DotDotDot)
+        } else if self.eat(&token::DotDotEq) {
+            RangeEnd::Included(RangeSyntax::DotDotEq)
+        } else if self.eat(&token::DotDot) {
+            self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_span);
+            RangeEnd::Excluded
+        } else {
+            return None;
+        };
+        Some(respan(self.prev_span, re))
     }
 
-    /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
-    fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
-        let lo = self.prev_span;
-        let end = self.parse_pat_range_end()?;
-        let range_span = lo.to(end.span);
-        let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new());
-
-        self.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
-            .span_suggestion(
-                range_span,
-                "try using the minimum value for the type",
-                format!("MIN{}{}", form, pprust::expr_to_string(&end)),
-                Applicability::HasPlaceholders,
-            )
-            .emit();
-
-        Ok(PatKind::Range(begin, end, respan(lo, re)))
-    }
-
-    /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern  or recover
-    /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
-    fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
-        if self.is_pat_range_end_start() {
+    /// Parse a range pattern `$begin $form $end?` where `$form = ".." | "..." | "..=" ;`.
+    /// `$begin $form` has already been parsed.
+    fn parse_pat_range_begin_with(
+        &mut self,
+        begin: P<Expr>,
+        re: Spanned<RangeEnd>,
+    ) -> PResult<'a, PatKind> {
+        let end = if self.is_pat_range_end_start(0) {
             // Parsing e.g. `X..=Y`.
-            self.parse_pat_range_end()
+            Some(self.parse_pat_range_end()?)
         } else {
             // Parsing e.g. `X..`.
-            let range_span = begin.span.to(self.prev_span);
+            self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span));
+            if let RangeEnd::Included(_) = re.node {
+                // FIXME(Centril): Consider semantic errors instead in `ast_validation`.
+                // Possibly also do this for `X..=` in *expression* contexts.
+                self.error_inclusive_range_with_no_end(re.span);
+            }
+            None
+        };
+        Ok(PatKind::Range(Some(begin), end, re))
+    }
 
-            self.struct_span_err(
-                range_span,
-                &format!("`X{}` range patterns are not supported", form),
+    pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
+        struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
+            .span_suggestion_short(
+                span,
+                "use `..` instead",
+                "..".to_string(),
+                Applicability::MachineApplicable,
             )
-            .span_suggestion(
-                range_span,
-                "try using the maximum value for the type",
-                format!("{}{}MAX", pprust::expr_to_string(&begin), form),
-                Applicability::HasPlaceholders,
-            )
+            .note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
             .emit();
+    }
 
-            Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new()))
+    /// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
+    ///
+    /// The form `...X` is prohibited to reduce confusion with the potential
+    /// expression syntax `...expr` for splatting in expressions.
+    fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
+        let end = self.parse_pat_range_end()?;
+        self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_span));
+        if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node {
+            *syn = RangeSyntax::DotDotEq;
+            self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
+                .span_suggestion_short(
+                    re.span,
+                    "use `..=` instead",
+                    "..=".to_string(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
         }
+        Ok(PatKind::Range(None, Some(end), re))
+    }
+
+    /// Is the token `dist` away from the current suitable as the start of a range patterns end?
+    fn is_pat_range_end_start(&self, dist: usize) -> bool {
+        self.look_ahead(dist, |t| {
+            t.is_path_start() // e.g. `MY_CONST`;
+                || t.kind == token::Dot // e.g. `.5` for recovery;
+                || t.can_begin_literal_or_bool() // e.g. `42`.
+                || t.is_whole_expr()
+        })
     }
 
     fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 4122aa1..a4cc9fa 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -3,10 +3,9 @@
 
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
-use rustc_error_codes::*;
-use rustc_errors::{pluralize, Applicability, PResult};
+use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, sym};
 use syntax::ast::{
     self, BareFnTy, FunctionRetTy, GenericParam, Ident, Lifetime, MutTy, Ty, TyKind,
 };
@@ -15,9 +14,28 @@
 };
 use syntax::ast::{Mac, Mutability};
 use syntax::ptr::P;
-use syntax::struct_span_err;
 use syntax::token::{self, Token};
 
+/// Any `?` or `?const` modifiers that appear at the start of a bound.
+struct BoundModifiers {
+    /// `?Trait`.
+    maybe: Option<Span>,
+
+    /// `?const Trait`.
+    maybe_const: Option<Span>,
+}
+
+impl BoundModifiers {
+    fn to_trait_bound_modifier(&self) -> TraitBoundModifier {
+        match (self.maybe, self.maybe_const) {
+            (None, None) => TraitBoundModifier::None,
+            (Some(_), None) => TraitBoundModifier::Maybe,
+            (None, Some(_)) => TraitBoundModifier::MaybeConst,
+            (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
+        }
+    }
+}
+
 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
 /// `IDENT<<u8 as Trait>::AssocTy>`.
 ///
@@ -196,6 +214,8 @@
         lo: Span,
         parse_plus: bool,
     ) -> PResult<'a, TyKind> {
+        assert_ne!(self.token, token::Question);
+
         let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
         let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
         if parse_plus {
@@ -422,12 +442,15 @@
         let has_parens = self.eat(&token::OpenDelim(token::Paren));
         let inner_lo = self.token.span;
         let is_negative = self.eat(&token::Not);
-        let question = self.eat(&token::Question).then_some(self.prev_span);
+
+        let modifiers = self.parse_ty_bound_modifiers();
         let bound = if self.token.is_lifetime() {
-            self.parse_generic_lt_bound(lo, inner_lo, has_parens, question)?
+            self.error_lt_bound_with_modifiers(modifiers);
+            self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
         } else {
-            self.parse_generic_ty_bound(lo, has_parens, question)?
+            self.parse_generic_ty_bound(lo, has_parens, modifiers)?
         };
+
         Ok(if is_negative { Err(anchor_lo.to(self.prev_span)) } else { Ok(bound) })
     }
 
@@ -440,9 +463,7 @@
         lo: Span,
         inner_lo: Span,
         has_parens: bool,
-        question: Option<Span>,
     ) -> PResult<'a, GenericBound> {
-        self.error_opt_out_lifetime(question);
         let bound = GenericBound::Outlives(self.expect_lifetime());
         if has_parens {
             // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
@@ -452,8 +473,17 @@
         Ok(bound)
     }
 
-    fn error_opt_out_lifetime(&self, question: Option<Span>) {
-        if let Some(span) = question {
+    /// Emits an error if any trait bound modifiers were present.
+    fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
+        if let Some(span) = modifiers.maybe_const {
+            self.struct_span_err(
+                span,
+                "`?const` may only modify trait bounds, not lifetime bounds",
+            )
+            .emit();
+        }
+
+        if let Some(span) = modifiers.maybe {
             self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
                 .emit();
         }
@@ -471,7 +501,7 @@
             err.span_suggestion_short(
                 lo.to(self.prev_span),
                 "remove the parentheses",
-                snippet.to_owned(),
+                snippet,
                 Applicability::MachineApplicable,
             );
         }
@@ -479,24 +509,57 @@
         Ok(())
     }
 
+    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `?const Trait`.
+    ///
+    /// If no modifiers are present, this does not consume any tokens.
+    ///
+    /// ```
+    /// TY_BOUND_MODIFIERS = "?" ["const" ["?"]]
+    /// ```
+    fn parse_ty_bound_modifiers(&mut self) -> BoundModifiers {
+        if !self.eat(&token::Question) {
+            return BoundModifiers { maybe: None, maybe_const: None };
+        }
+
+        // `? ...`
+        let first_question = self.prev_span;
+        if !self.eat_keyword(kw::Const) {
+            return BoundModifiers { maybe: Some(first_question), maybe_const: None };
+        }
+
+        // `?const ...`
+        let maybe_const = first_question.to(self.prev_span);
+        self.sess.gated_spans.gate(sym::const_trait_bound_opt_out, maybe_const);
+        if !self.eat(&token::Question) {
+            return BoundModifiers { maybe: None, maybe_const: Some(maybe_const) };
+        }
+
+        // `?const ? ...`
+        let second_question = self.prev_span;
+        BoundModifiers { maybe: Some(second_question), maybe_const: Some(maybe_const) }
+    }
+
     /// Parses a type bound according to:
     /// ```
     /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
-    /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
+    /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
     /// ```
+    ///
+    /// For example, this grammar accepts `?const ?for<'a: 'b> m::Trait<'a>`.
     fn parse_generic_ty_bound(
         &mut self,
         lo: Span,
         has_parens: bool,
-        question: Option<Span>,
+        modifiers: BoundModifiers,
     ) -> PResult<'a, GenericBound> {
         let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
         let path = self.parse_path(PathStyle::Type)?;
         if has_parens {
             self.expect(&token::CloseDelim(token::Paren))?;
         }
+
+        let modifier = modifiers.to_trait_bound_modifier();
         let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
-        let modifier = question.map_or(TraitBoundModifier::None, |_| TraitBoundModifier::Maybe);
         Ok(GenericBound::Trait(poly_trait, modifier))
     }
 
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index f089361..84562fb 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -4,10 +4,10 @@
 
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
+use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Symbol};
 use syntax::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
-use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
-use syntax::sess::ParseSess;
 use syntax::tokenstream::DelimSpan;
 
 pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index ced933b..338808f 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -12,12 +12,11 @@
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_index = { path = "../librustc_index" }
-rustc_parse = { path = "../librustc_parse" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs
index 30ec0fe..faa85f6 100644
--- a/src/librustc_passes/check_const.rs
+++ b/src/librustc_passes/check_const.rs
@@ -7,18 +7,17 @@
 //! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
 use rustc::session::config::nightly_options;
+use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::{sym, Span, Symbol};
 use syntax::ast::Mutability;
-use syntax::feature_gate::feature_err;
-use syntax::span_err;
 
 use std::fmt;
 
@@ -154,7 +153,7 @@
             required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
 
         match missing_gates.as_slice() {
-            &[] => span_err!(self.tcx.sess, span, E0744, "{}", msg),
+            &[] => struct_span_err!(self.tcx.sess, span, E0744, "{}", msg).emit(),
 
             // If the user enabled `#![feature(const_loop)]` but not `#![feature(const_if_match)]`,
             // explain why their `while` loop is being rejected.
@@ -200,7 +199,9 @@
 }
 
 impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 0c435a1..2ff9d74 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -2,8 +2,7 @@
 // closely. The idea is that all reachable symbols are live, codes called
 // from live codes are live, and everything else is dead.
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::lint;
+use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::privacy;
 use rustc::ty::{self, DefIdTree, TyCtxt};
@@ -11,8 +10,10 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{Node, PatKind, TyKind};
+use rustc_session::lint;
 
 use rustc_span;
 use rustc_span::symbol::sym;
@@ -210,7 +211,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -402,10 +405,10 @@
                     }
                 }
             }
-            hir::ItemKind::Impl(.., ref opt_trait, _, impl_item_refs) => {
-                for impl_item_ref in impl_item_refs {
+            hir::ItemKind::Impl { ref of_trait, items, .. } => {
+                for impl_item_ref in items {
                     let impl_item = self.krate.impl_item(impl_item_ref.id);
-                    if opt_trait.is_some()
+                    if of_trait.is_some()
                         || has_allow_dead_code_or_lang_attr(
                             self.tcx,
                             impl_item.hir_id,
@@ -563,11 +566,13 @@
 }
 
 impl Visitor<'tcx> for DeadVisitor<'tcx> {
+    type Map = Map<'tcx>;
+
     /// Walk nested items in place so that we don't report dead-code
     /// on inner functions when the outer function is already getting
     /// an error. We could do this also by checking the parents, but
     /// this is how the code is setup and it seems harmless enough.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -581,7 +586,7 @@
                 | hir::ItemKind::Struct(..)
                 | hir::ItemKind::Union(..)
                 | hir::ItemKind::Trait(..)
-                | hir::ItemKind::Impl(..) => {
+                | hir::ItemKind::Impl { .. } => {
                     // FIXME(66095): Because item.span is annotated with things
                     // like expansion data, and ident.span isn't, we use the
                     // def_span method if it's part of a macro invocation
diff --git a/src/librustc_passes/diagnostic_items.rs b/src/librustc_passes/diagnostic_items.rs
index f84f998..8d220a3 100644
--- a/src/librustc_passes/diagnostic_items.rs
+++ b/src/librustc_passes/diagnostic_items.rs
@@ -73,7 +73,7 @@
                 )),
             };
             if let Some(span) = tcx.hir().span_if_local(original_def_id) {
-                span_note!(&mut err, span, "first defined here.");
+                err.span_note(span, "first defined here");
             } else {
                 err.note(&format!(
                     "first defined in crate `{}`.",
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index 91b787b..d36114f 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -3,16 +3,15 @@
 use rustc::session::{config, Session};
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use syntax::attr;
 use syntax::entry::EntryPointType;
 
-use rustc_error_codes::*;
-
 struct EntryContext<'a, 'tcx> {
     session: &'a Session,
 
@@ -108,7 +107,8 @@
             if ctxt.main_fn.is_none() {
                 ctxt.main_fn = Some((item.hir_id, item.span));
             } else {
-                span_err!(ctxt.session, item.span, E0136, "multiple `main` functions");
+                struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions")
+                    .emit();
             }
         }
         EntryPointType::OtherMain => {
@@ -166,8 +166,9 @@
     }
 
     // There is no main function.
-    let mut err = struct_err!(
+    let mut err = struct_span_err!(
         tcx.sess,
+        DUMMY_SP,
         E0601,
         "`main` function not found in crate `{}`",
         tcx.crate_name(LOCAL_CRATE)
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 3eca602..b6ca2b3 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -2,10 +2,11 @@
 // pieces of AST and HIR. The resulting numbers are good approximations but not
 // completely accurate (some things might be counted twice, others missed).
 
-use rustc::hir::intravisit as hir_visit;
+use rustc::hir::map::Map;
 use rustc::util::common::to_readable_str;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
+use rustc_hir::intravisit as hir_visit;
 use rustc_hir::HirId;
 use rustc_span::Span;
 use syntax::ast::{self, AttrId, NodeId};
@@ -92,7 +93,9 @@
         hir_visit::walk_param(self, param)
     }
 
-    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> {
         panic!("visit_nested_xxx must be manually implemented in this visitor")
     }
 
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index cc31191..7821990 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -1,17 +1,16 @@
+use rustc::hir::map::Map;
 use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir as hir;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::Idx;
 use rustc_span::{sym, Span};
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 
-use rustc_error_codes::*;
-
 fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut ItemVisitor { tcx }.as_deep_visitor());
 }
@@ -123,7 +122,9 @@
 }
 
 impl Visitor<'tcx> for ItemVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -138,7 +139,9 @@
 }
 
 impl Visitor<'tcx> for ExprVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index a692c45..d746f09 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -7,19 +7,16 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![recursion_limit = "256"]
 
 #[macro_use]
 extern crate rustc;
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate syntax;
 
 use rustc::ty::query::Providers;
 
-pub mod ast_validation;
 mod check_const;
 pub mod dead;
 mod diagnostic_items;
diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs
index df3e4ee..2e306a1 100644
--- a/src/librustc_passes/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -4,17 +4,17 @@
 // and `#[unstable (..)]`), but are not declared in one single location
 // (unlike lang features), which means we need to collect them instead.
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::middle::lib_features::LibFeatures;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, Span};
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
 
-use rustc_error_codes::*;
-
 fn new_lib_features() -> LibFeatures {
     LibFeatures { stable: Default::default(), unstable: Default::default() }
 }
@@ -112,7 +112,9 @@
 }
 
 impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 3ae5e4f..7718139 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -96,15 +96,16 @@
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
-use errors::Applicability;
-use rustc::hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -153,7 +154,9 @@
 }
 
 impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -1061,7 +1064,7 @@
                             .sess
                             .struct_span_err(expr.span, "`break` to unknown label")
                             .emit();
-                        errors::FatalError.raise()
+                        rustc_errors::FatalError.raise()
                     }
                 }
             }
@@ -1348,7 +1351,9 @@
 // Checking for error conditions
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1508,13 +1513,16 @@
                 if ln == self.s.exit_ln { false } else { self.assigned_on_exit(ln, var).is_some() };
 
             if is_assigned {
-                self.ir.tcx.lint_hir_note(
-                    lint::builtin::UNUSED_VARIABLES,
-                    hir_id,
-                    spans,
-                    &format!("variable `{}` is assigned to, but never used", name),
-                    &format!("consider using `_{}` instead", name),
-                );
+                self.ir
+                    .tcx
+                    .struct_span_lint_hir(
+                        lint::builtin::UNUSED_VARIABLES,
+                        hir_id,
+                        spans,
+                        &format!("variable `{}` is assigned to, but never used", name),
+                    )
+                    .note(&format!("consider using `_{}` instead", name))
+                    .emit();
             } else {
                 let mut err = self.ir.tcx.struct_span_lint_hir(
                     lint::builtin::UNUSED_VARIABLES,
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index ec8c8ee..69d6b38 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -1,19 +1,15 @@
 use Context::*;
 
-use rustc::session::Session;
-
-use errors::Applicability;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Destination, Movability, Node};
+use rustc_session::Session;
 use rustc_span::Span;
-use syntax::struct_span_err;
-
-use rustc_error_codes::*;
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 enum Context {
@@ -45,7 +41,9 @@
 }
 
 impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
+    type Map = Map<'hir>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.hir_map)
     }
 
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index 9b52940..6678980 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -5,8 +5,7 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
-use rustc::hir::intravisit;
-use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::middle::privacy;
 use rustc::session::config;
@@ -18,6 +17,8 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::intravisit;
+use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirIdSet, Node};
 use rustc_target::spec::abi::Abi;
@@ -34,7 +35,7 @@
         hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => {
             return true;
         }
-        hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => {
+        hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
             let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
             generics.requires_monomorphization(tcx)
         }
@@ -82,7 +83,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -178,7 +181,7 @@
                             // does too.
                             let impl_hir_id = self.tcx.hir().as_local_hir_id(impl_did).unwrap();
                             match self.tcx.hir().expect_item(impl_hir_id).kind {
-                                hir::ItemKind::Impl(..) => {
+                                hir::ItemKind::Impl { .. } => {
                                     let generics = self.tcx.generics_of(impl_did);
                                     generics.requires_monomorphization(self.tcx)
                                 }
@@ -263,7 +266,7 @@
                     | hir::ItemKind::Static(..)
                     | hir::ItemKind::Mod(..)
                     | hir::ItemKind::ForeignMod(..)
-                    | hir::ItemKind::Impl(..)
+                    | hir::ItemKind::Impl { .. }
                     | hir::ItemKind::Trait(..)
                     | hir::ItemKind::TraitAlias(..)
                     | hir::ItemKind::Struct(..)
@@ -346,9 +349,9 @@
         }
 
         // We need only trait impls here, not inherent impls, and only non-exported ones
-        if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.kind {
+        if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind {
             if !self.access_levels.is_reachable(item.hir_id) {
-                self.worklist.extend(impl_item_refs.iter().map(|ii_ref| ii_ref.id.hir_id));
+                self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.hir_id));
 
                 let trait_def_id = match trait_ref.path.res {
                     Res::Def(DefKind::Trait, def_id) => def_id,
diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs
index f2aa5af..e79ca5c 100644
--- a/src/librustc_passes/region.rs
+++ b/src/librustc_passes/region.rs
@@ -6,17 +6,19 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::middle::region::*;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt};
 use rustc_index::vec::Idx;
 use rustc_span::source_map;
 use rustc_span::Span;
+use syntax::walk_list;
 
 use std::mem;
 
@@ -694,7 +696,9 @@
 }
 
 impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 68e2bc5..320b433 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -1,31 +1,31 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability::{DeprecationEntry, Index};
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::traits::misc::can_type_implement_copy;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Generics, HirId, Item, StructField, Variant};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use syntax::ast::Attribute;
 use syntax::attr::{self, Stability};
-use syntax::feature_gate::feature_err;
 
 use std::cmp::Ordering;
 use std::mem::replace;
 use std::num::NonZeroU32;
 
-use rustc_error_codes::*;
-
 #[derive(PartialEq)]
 enum AnnotationKind {
     // Annotation is required if not inherited from unstable parents
@@ -89,7 +89,7 @@
                 // deprecated_since and its reason.
                 if let Some(parent_stab) = self.parent_stab {
                     if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
-                        stab.rustc_depr = parent_stab.rustc_depr.clone()
+                        stab.rustc_depr = parent_stab.rustc_depr
                     }
                 }
 
@@ -203,7 +203,9 @@
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -215,11 +217,11 @@
             // they don't have their own stability. They still can be annotated as unstable
             // and propagate this unstability to children, but this annotation is completely
             // optional. They inherit stability from their parents when unannotated.
-            hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {
                 self.in_trait_impl = false;
                 kind = AnnotationKind::Container;
             }
-            hir::ItemKind::Impl(.., Some(_), _, _) => {
+            hir::ItemKind::Impl { of_trait: Some(_), .. } => {
                 self.in_trait_impl = true;
             }
             hir::ItemKind::Struct(ref sd, _) => {
@@ -292,7 +294,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -302,7 +306,7 @@
             // they don't have their own stability. They still can be annotated as unstable
             // and propagate this unstability to children, but this annotation is completely
             // optional. They inherit stability from their parents when unannotated.
-            hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {}
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {}
 
             _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant()),
         }
@@ -428,10 +432,12 @@
 }
 
 impl Visitor<'tcx> for Checker<'tcx> {
+    type Map = Map<'tcx>;
+
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -455,9 +461,9 @@
             // For implementations of traits, check the stability of each item
             // individually as it's possible to have a stable trait with unstable
             // items.
-            hir::ItemKind::Impl(.., Some(ref t), _, impl_item_refs) => {
+            hir::ItemKind::Impl { of_trait: Some(ref t), items, .. } => {
                 if let Res::Def(DefKind::Trait, trait_did) = t.path.res {
-                    for impl_item_ref in impl_item_refs {
+                    for impl_item_ref in items {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         let trait_item_def_id = self
                             .tcx
diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml
index 54cceca..2214838 100644
--- a/src/librustc_plugin_impl/Cargo.toml
+++ b/src/librustc_plugin_impl/Cargo.toml
@@ -12,8 +12,9 @@
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
+rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_plugin_impl/lib.rs b/src/librustc_plugin_impl/lib.rs
index 682d223..10712eb 100644
--- a/src/librustc_plugin_impl/lib.rs
+++ b/src/librustc_plugin_impl/lib.rs
@@ -9,7 +9,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(nll)]
 
-use rustc::lint::LintStore;
+use rustc_lint::LintStore;
 
 pub mod build;
 pub mod load;
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index 2215e49..84549c0 100644
--- a/src/librustc_plugin_impl/load.rs
+++ b/src/librustc_plugin_impl/load.rs
@@ -3,18 +3,16 @@
 use crate::Registry;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::Session;
+use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
-
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use syntax::ast::{Crate, Ident};
+
 use std::borrow::ToOwned;
 use std::env;
 use std::mem;
 use std::path::PathBuf;
-use syntax::ast::{Crate, Ident};
-use syntax::struct_span_err;
-
-use rustc_error_codes::*;
 
 /// Pointer to a registrar function.
 type PluginRegistrarFn = fn(&mut Registry<'_>);
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
index 6c9a2d6..4f341b5 100644
--- a/src/librustc_privacy/Cargo.toml
+++ b/src/librustc_privacy/Cargo.toml
@@ -10,10 +10,10 @@
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 log = "0.4"
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index c932e8b..60bf271 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -3,11 +3,8 @@
 #![feature(nll)]
 #![recursion_limit = "256"]
 
-#[macro_use]
-extern crate syntax;
-
 use rustc::bug;
-use rustc::hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::fold::TypeVisitor;
@@ -15,9 +12,11 @@
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
 use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
 use rustc_span::hygiene::Transparency;
 use rustc_span::symbol::{kw, sym};
@@ -28,8 +27,6 @@
 use std::marker::PhantomData;
 use std::{cmp, fmt, mem};
 
-use rustc_error_codes::*;
-
 ////////////////////////////////////////////////////////////////////////////////
 /// Generic infrastructure used to implement specific visitors below.
 ////////////////////////////////////////////////////////////////////////////////
@@ -94,7 +91,7 @@
         let ty::GenericPredicates { parent: _, predicates } = predicates;
         for (predicate, _span) in predicates {
             match predicate {
-                ty::Predicate::Trait(poly_predicate) => {
+                ty::Predicate::Trait(poly_predicate, _) => {
                     let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder();
                     if self.visit_trait(trait_ref) {
                         return true;
@@ -256,8 +253,8 @@
                 Node::ImplItem(impl_item) => {
                     match tcx.hir().get(tcx.hir().get_parent_item(hir_id)) {
                         Node::Item(item) => match &item.kind {
-                            hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis,
-                            hir::ItemKind::Impl(.., Some(trait_ref), _, _) => {
+                            hir::ItemKind::Impl { of_trait: None, .. } => &impl_item.vis,
+                            hir::ItemKind::Impl { of_trait: Some(trait_ref), .. } => {
                                 return def_id_visibility(tcx, trait_ref.path.res.def_id());
                             }
                             kind => bug!("unexpected item kind: {:?}", kind),
@@ -374,7 +371,9 @@
 }
 
 impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
     fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) {
@@ -651,6 +650,9 @@
             if let Some(item) = module
                 .res
                 .and_then(|res| res.mod_def_id())
+                // If the module is `self`, i.e. the current crate,
+                // there will be no corresponding item.
+                .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
                 .and_then(|def_id| self.tcx.hir().as_local_hir_id(def_id))
                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
             {
@@ -672,15 +674,17 @@
 }
 
 impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let inherited_item_level = match item.kind {
-            hir::ItemKind::Impl(..) => {
+            hir::ItemKind::Impl { .. } => {
                 Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels)
             }
             // Foreign modules inherit level from parents.
@@ -724,9 +728,9 @@
                     }
                 }
             }
-            hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => {
-                for impl_item_ref in impl_item_refs {
-                    if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() {
+            hir::ItemKind::Impl { ref of_trait, items, .. } => {
+                for impl_item_ref in items {
+                    if of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
                         self.update(impl_item_ref.id.hir_id, item_level);
                     }
                 }
@@ -821,11 +825,11 @@
                 }
             }
             // Visit everything except for private impl items.
-            hir::ItemKind::Impl(.., impl_item_refs) => {
+            hir::ItemKind::Impl { items, .. } => {
                 if item_level.is_some() {
                     self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
 
-                    for impl_item_ref in impl_item_refs {
+                    for impl_item_ref in items {
                         let impl_item_level = self.get(impl_item_ref.id.hir_id);
                         if impl_item_level.is_some() {
                             self.reach(impl_item_ref.id.hir_id, impl_item_level)
@@ -1041,9 +1045,11 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1181,9 +1187,11 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1227,7 +1235,7 @@
             // The traits' privacy in bodies is already checked as a part of trait object types.
             let bounds = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref);
 
-            for (trait_predicate, _) in bounds.trait_bounds {
+            for (trait_predicate, _, _) in bounds.trait_bounds {
                 if self.visit_trait(*trait_predicate.skip_binder()) {
                     return;
                 }
@@ -1439,7 +1447,9 @@
 }
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1465,9 +1475,11 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -1496,7 +1508,7 @@
             // (i.e., we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible).
-            hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, impl_item_refs) => {
+            hir::ItemKind::Impl { generics: ref g, ref of_trait, ref self_ty, items, .. } => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // `impl [... for] Public<...>`, but not `impl [... for]
@@ -1511,7 +1523,7 @@
                         at_outer_type: true,
                         outer_type_is_public_path: false,
                     };
-                    visitor.visit_ty(&self_);
+                    visitor.visit_ty(&self_ty);
                     self_contains_private = visitor.contains_private;
                     self_is_public_path = visitor.outer_type_is_public_path;
                 }
@@ -1519,7 +1531,7 @@
                 // Miscellaneous info about the impl:
 
                 // `true` iff this is `impl Private for ...`.
-                let not_private_trait = trait_ref.as_ref().map_or(
+                let not_private_trait = of_trait.as_ref().map_or(
                     true, // no trait counts as public trait
                     |tr| {
                         let did = tr.path.res.def_id();
@@ -1540,8 +1552,8 @@
                 // directly because we might have `impl<T: Foo<Private>> ...`,
                 // and we shouldn't warn about the generics if all the methods
                 // are private (because `T` won't be visible externally).
-                let trait_or_some_public_method = trait_ref.is_some()
-                    || impl_item_refs.iter().any(|impl_item_ref| {
+                let trait_or_some_public_method = of_trait.is_some()
+                    || items.iter().any(|impl_item_ref| {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         match impl_item.kind {
                             hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => {
@@ -1556,9 +1568,9 @@
                 if !self_contains_private && not_private_trait && trait_or_some_public_method {
                     intravisit::walk_generics(self, g);
 
-                    match *trait_ref {
+                    match of_trait {
                         None => {
-                            for impl_item_ref in impl_item_refs {
+                            for impl_item_ref in items {
                                 // This is where we choose whether to walk down
                                 // further into the impl to check its items. We
                                 // should only walk into public items so that we
@@ -1580,7 +1592,7 @@
                                 }
                             }
                         }
-                        Some(ref tr) => {
+                        Some(tr) => {
                             // Any private types in a trait impl fall into three
                             // categories.
                             // 1. mentioned in the trait definition
@@ -1597,7 +1609,7 @@
                             intravisit::walk_path(self, &tr.path);
 
                             // Those in 3. are warned with this call.
-                            for impl_item_ref in impl_item_refs {
+                            for impl_item_ref in items {
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                                 if let hir::ImplItemKind::TyAlias(ref ty) = impl_item.kind {
                                     self.visit_ty(ty);
@@ -1605,11 +1617,11 @@
                             }
                         }
                     }
-                } else if trait_ref.is_none() && self_is_public_path {
+                } else if of_trait.is_none() && self_is_public_path {
                     // `impl Public<Private> { ... }`. Any public static
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
-                    for impl_item_ref in impl_item_refs {
+                    for impl_item_ref in items {
                         if self.item_is_public(&impl_item_ref.id.hir_id, &impl_item_ref.vis) {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
@@ -1908,7 +1920,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -1981,12 +1995,12 @@
             // Subitems of inherent impls have their own publicity.
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity.
-            hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => {
+            hir::ItemKind::Impl { ref of_trait, items, .. } => {
                 let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default());
                 self.check(item.hir_id, impl_vis).generics().predicates();
-                for impl_item_ref in impl_item_refs {
+                for impl_item_ref in items {
                     let impl_item = tcx.hir().impl_item(impl_item_ref.id);
-                    let impl_item_vis = if trait_ref.is_none() {
+                    let impl_item_vis = if of_trait.is_none() {
                         min(
                             ty::Visibility::from_hir(&impl_item.vis, item.hir_id, tcx),
                             impl_vis,
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 01e5d75..c4cc6b0 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -14,16 +14,15 @@
 bitflags = "1.2.1"
 log = "0.4"
 syntax = { path = "../libsyntax" }
-rustc_expand = { path = "../librustc_expand" }
 arena = { path = "../libarena" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
-rustc_span = { path = "../librustc_span" }
 rustc = { path = "../librustc" }
 rustc_ast_lowering = { path = "../librustc_ast_lowering" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_expand = { path = "../librustc_expand" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 46dde45..7ff0762 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -20,18 +20,13 @@
 use rustc::hir::exports::Export;
 use rustc::middle::cstore::CrateStore;
 use rustc::ty;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, Applicability};
+use rustc_expand::base::SyntaxExtension;
+use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_metadata::creader::LoadedMacro;
-
-use rustc_data_structures::sync::Lrc;
-use std::cell::Cell;
-use std::ptr;
-
-use errors::Applicability;
-
-use rustc_expand::base::SyntaxExtension;
-use rustc_expand::expand::AstFragment;
 use rustc_span::hygiene::{ExpnId, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym};
@@ -40,13 +35,12 @@
 use syntax::ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use syntax::ast::{Ident, Name};
 use syntax::attr;
-use syntax::span_err;
 use syntax::token::{self, Token};
 use syntax::visit::{self, Visitor};
 
 use log::debug;
-
-use rustc_error_codes::*;
+use std::cell::Cell;
+use std::ptr;
 
 type Res = def::Res<NodeId>;
 
@@ -820,7 +814,7 @@
             }
 
             // These items do not add names to modules.
-            ItemKind::Impl(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
+            ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
 
             ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
         }
@@ -954,22 +948,27 @@
         for attr in &item.attrs {
             if attr.check_name(sym::macro_use) {
                 if self.parent_scope.module.parent.is_some() {
-                    span_err!(
+                    struct_span_err!(
                         self.r.session,
                         item.span,
                         E0468,
                         "an `extern crate` loading macros must be at the crate root"
-                    );
+                    )
+                    .emit();
                 }
                 if let ItemKind::ExternCrate(Some(orig_name)) = item.kind {
                     if orig_name == kw::SelfLower {
-                        self.r.session.span_err(
-                            attr.span,
-                            "`macro_use` is not supported on `extern crate self`",
-                        );
+                        self.r
+                            .session
+                            .struct_span_err(
+                                attr.span,
+                                "`#[macro_use]` is not supported on `extern crate self`",
+                            )
+                            .emit();
                     }
                 }
-                let ill_formed = |span| span_err!(self.r.session, span, E0466, "bad macro import");
+                let ill_formed =
+                    |span| struct_span_err!(self.r.session, span, E0466, "bad macro import").emit();
                 match attr.meta() {
                     Some(meta) => match meta.kind {
                         MetaItemKind::Word => {
@@ -1042,7 +1041,8 @@
                         allow_shadowing,
                     );
                 } else {
-                    span_err!(self.r.session, ident.span, E0469, "imported macro not found");
+                    struct_span_err!(self.r.session, ident.span, E0469, "imported macro not found")
+                        .emit();
                 }
             }
         }
@@ -1053,10 +1053,10 @@
     fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
         for attr in attrs {
             if attr.check_name(sym::macro_escape) {
-                let msg = "macro_escape is a deprecated synonym for macro_use";
+                let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`";
                 let mut err = self.r.session.struct_span_warn(attr.span, msg);
                 if let ast::AttrStyle::Inner = attr.style {
-                    err.help("consider an outer attribute, `#[macro_use]` mod ...").emit();
+                    err.help("try an outer attribute: `#[macro_use]`").emit();
                 } else {
                     err.emit();
                 }
@@ -1065,7 +1065,7 @@
             }
 
             if !attr.is_word() {
-                self.r.session.span_err(attr.span, "arguments to macro_use are not allowed here");
+                self.r.session.span_err(attr.span, "arguments to `macro_use` are not allowed here");
             }
             return true;
         }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 6561072..4a6df92 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -26,9 +26,10 @@
 use crate::imports::ImportDirectiveSubclass;
 use crate::Resolver;
 
-use errors::pluralize;
 use rustc::{lint, ty};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::pluralize;
+use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::node_id::NodeMap;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use syntax::ast;
@@ -317,7 +318,7 @@
                 unused.use_tree_id,
                 ms,
                 &msg,
-                lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
+                BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
             );
         }
     }
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index f564ea6..696ba0e 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -104,7 +104,7 @@
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into, the better
         let def_data = match &i.kind {
-            ItemKind::Impl(..) => DefPathData::Impl,
+            ItemKind::Impl { .. } => DefPathData::Impl,
             ItemKind::Mod(..) if i.ident.name == kw::Invalid => {
                 return visit::walk_item(self, i);
             }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index ba3d231..77dfe3d 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,32 +1,31 @@
 use std::cmp::Reverse;
 
-use errors::{Applicability, DiagnosticBuilder};
 use log::debug;
 use rustc::bug;
 use rustc::session::Session;
 use rustc::ty::{self, DefIdTree};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_feature::BUILTIN_ATTRIBUTES;
+use rustc_hir as hir;
 use rustc_hir::def::Namespace::{self, *};
-use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span};
 use syntax::ast::{self, Ident, Path};
 use syntax::print::pprust;
-use syntax::struct_span_err;
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::path_names_to_string;
-use crate::VisResolutionError;
+use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
 use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
 
-use rustc_error_codes::*;
-
 type Res = def::Res<ast::NodeId>;
 
 /// A vector of spans and replacements, a message and applicability.
@@ -781,8 +780,14 @@
                 suggestion.candidate.to_string(),
                 Applicability::MaybeIncorrect,
             );
-            let def_span =
-                suggestion.res.opt_def_id().and_then(|def_id| self.definitions.opt_span(def_id));
+            let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
+                LOCAL_CRATE => self.definitions.opt_span(def_id),
+                _ => Some(
+                    self.session
+                        .source_map()
+                        .def_span(self.cstore().get_span_untracked(def_id, self.session)),
+                ),
+            });
             if let Some(span) = def_span {
                 err.span_label(
                     span,
@@ -797,6 +802,163 @@
         }
         false
     }
+
+    fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
+        let res = b.res();
+        if b.span.is_dummy() {
+            let add_built_in = match b.res() {
+                // These already contain the "built-in" prefix or look bad with it.
+                Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => false,
+                _ => true,
+            };
+            let (built_in, from) = if from_prelude {
+                ("", " from prelude")
+            } else if b.is_extern_crate()
+                && !b.is_import()
+                && self.session.opts.externs.get(&ident.as_str()).is_some()
+            {
+                ("", " passed with `--extern`")
+            } else if add_built_in {
+                (" built-in", "")
+            } else {
+                ("", "")
+            };
+
+            let article = if built_in.is_empty() { res.article() } else { "a" };
+            format!(
+                "{a}{built_in} {thing}{from}",
+                a = article,
+                thing = res.descr(),
+                built_in = built_in,
+                from = from
+            )
+        } else {
+            let introduced = if b.is_import() { "imported" } else { "defined" };
+            format!("the {thing} {introduced} here", thing = res.descr(), introduced = introduced)
+        }
+    }
+
+    crate fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
+        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
+        let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
+            // We have to print the span-less alternative first, otherwise formatting looks bad.
+            (b2, b1, misc2, misc1, true)
+        } else {
+            (b1, b2, misc1, misc2, false)
+        };
+
+        let mut err = struct_span_err!(
+            self.session,
+            ident.span,
+            E0659,
+            "`{ident}` is ambiguous ({why})",
+            ident = ident,
+            why = kind.descr()
+        );
+        err.span_label(ident.span, "ambiguous name");
+
+        let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
+            let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
+            let note_msg = format!(
+                "`{ident}` could{also} refer to {what}",
+                ident = ident,
+                also = also,
+                what = what
+            );
+
+            let thing = b.res().descr();
+            let mut help_msgs = Vec::new();
+            if b.is_glob_import()
+                && (kind == AmbiguityKind::GlobVsGlob
+                    || kind == AmbiguityKind::GlobVsExpanded
+                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
+            {
+                help_msgs.push(format!(
+                    "consider adding an explicit import of \
+                     `{ident}` to disambiguate",
+                    ident = ident
+                ))
+            }
+            if b.is_extern_crate() && ident.span.rust_2018() {
+                help_msgs.push(format!(
+                    "use `::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            }
+            if misc == AmbiguityErrorMisc::SuggestCrate {
+                help_msgs.push(format!(
+                    "use `crate::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            } else if misc == AmbiguityErrorMisc::SuggestSelf {
+                help_msgs.push(format!(
+                    "use `self::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            }
+
+            err.span_note(b.span, &note_msg);
+            for (i, help_msg) in help_msgs.iter().enumerate() {
+                let or = if i == 0 { "" } else { "or " };
+                err.help(&format!("{}{}", or, help_msg));
+            }
+        };
+
+        could_refer_to(b1, misc1, "");
+        could_refer_to(b2, misc2, " also");
+        err.emit();
+    }
+
+    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+        let PrivacyError { ident, binding, .. } = *privacy_error;
+        let session = &self.session;
+        let mk_struct_span_error = |is_constructor| {
+            let mut descr = binding.res().descr().to_string();
+            if is_constructor {
+                descr += " constructor";
+            }
+            if binding.is_import() {
+                descr += " import";
+            }
+
+            let mut err =
+                struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
+
+            err.span_label(ident.span, &format!("this {} is private", descr));
+            err.span_note(
+                session.source_map().def_span(binding.span),
+                &format!("the {} `{}` is defined here", descr, ident),
+            );
+
+            err
+        };
+
+        let mut err = if let NameBindingKind::Res(
+            Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
+            _,
+        ) = binding.kind
+        {
+            let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
+            if let Some(fields) = self.field_names.get(&def_id) {
+                let mut err = mk_struct_span_error(true);
+                let first_field = fields.first().expect("empty field list in the map");
+                err.span_label(
+                    fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
+                    "a constructor is private if any of the fields is private",
+                );
+                err
+            } else {
+                mk_struct_span_error(false)
+            }
+        } else {
+            mk_struct_span_error(false)
+        };
+
+        err.emit();
+    }
 }
 
 impl<'a, 'b> ImportResolver<'a, 'b> {
@@ -1284,3 +1446,74 @@
         }
     }
 }
+
+crate fn report_missing_lifetime_specifiers(
+    sess: &Session,
+    span: Span,
+    count: usize,
+) -> DiagnosticBuilder<'_> {
+    struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count))
+}
+
+crate fn add_missing_lifetime_specifiers_label(
+    err: &mut DiagnosticBuilder<'_>,
+    span: Span,
+    count: usize,
+    lifetime_names: &FxHashSet<ast::Ident>,
+    snippet: Option<&str>,
+    missing_named_lifetime_spots: &[&hir::Generics<'_>],
+) {
+    if count > 1 {
+        err.span_label(span, format!("expected {} lifetime parameters", count));
+    } else {
+        let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
+            err.span_suggestion(
+                span,
+                "consider using the named lifetime",
+                sugg,
+                Applicability::MaybeIncorrect,
+            );
+        };
+        let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg| {
+            err.span_label(span, "expected named lifetime parameter");
+
+            if let Some(generics) = missing_named_lifetime_spots.iter().last() {
+                let mut introduce_suggestion = vec![];
+                introduce_suggestion.push(match &generics.params {
+                    [] => (generics.span, "<'lifetime>".to_string()),
+                    [param, ..] => (param.span.shrink_to_lo(), "'lifetime, ".to_string()),
+                });
+                introduce_suggestion.push((span, sugg));
+                err.multipart_suggestion(
+                    "consider introducing a named lifetime parameter",
+                    introduce_suggestion,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        };
+
+        match (lifetime_names.len(), lifetime_names.iter().next(), snippet) {
+            (1, Some(name), Some("&")) => {
+                suggest_existing(err, format!("&{} ", name));
+            }
+            (1, Some(name), Some("'_")) => {
+                suggest_existing(err, name.to_string());
+            }
+            (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
+                suggest_existing(err, format!("{}<{}>", snippet, name));
+            }
+            (0, _, Some("&")) => {
+                suggest_new(err, "&'lifetime ".to_string());
+            }
+            (0, _, Some("'_")) => {
+                suggest_new(err, "'lifetime".to_string());
+            }
+            (0, _, Some(snippet)) if !snippet.ends_with(">") => {
+                suggest_new(err, format!("{}<'lifetime>", snippet));
+            }
+            _ => {
+                err.span_label(span, "expected lifetime parameter");
+            }
+        }
+    }
+}
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index 5ede056..55ce51e 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -11,26 +11,23 @@
 use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
-use errors::{pluralize, Applicability};
-
 use rustc::hir::exports::Export;
-use rustc::lint::builtin::BuiltinLintDiagnostics;
 use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
-use rustc::session::DiagnosticMessageId;
 use rustc::ty;
 use rustc::{bug, span_bug};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
+use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir::def::{self, PartialRes};
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span};
 use syntax::ast::{Ident, Name, NodeId};
+use syntax::unwrap_or;
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::{struct_span_err, unwrap_or};
-
-use rustc_error_codes::*;
 
 use log::*;
 
@@ -320,7 +317,11 @@
                        // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
                        !(self.last_import_segment && binding.is_extern_crate())
                         {
-                            self.privacy_errors.push(PrivacyError(path_span, ident, binding));
+                            self.privacy_errors.push(PrivacyError {
+                                ident,
+                                binding,
+                                dedup_span: path_span,
+                            });
                         }
 
                         Ok(binding)
@@ -719,7 +720,7 @@
         }
 
         if !errors.is_empty() {
-            self.throw_unresolved_import_error(errors.clone(), None);
+            self.throw_unresolved_import_error(errors, None);
         }
     }
 
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index fb7aacb..5e08ac8 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -11,9 +11,9 @@
 use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
-use log::debug;
 use rustc::{bug, lint, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::DiagnosticId;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
@@ -27,11 +27,10 @@
 use syntax::visit::{self, FnKind, Visitor};
 use syntax::{unwrap_or, walk_list};
 
+use log::debug;
 use std::collections::BTreeSet;
 use std::mem::replace;
 
-use rustc_error_codes::*;
-
 mod diagnostics;
 
 type Res = def::Res<NodeId>;
@@ -304,32 +303,21 @@
         }
     }
 
-    fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
-        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);
+    fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId {
+        use rustc_errors::error_code;
         match (self, has_unexpected_resolution) {
-            (PathSource::Trait(_), true) => "E0404",
-            (PathSource::Trait(_), false) => "E0405",
-            (PathSource::Type, true) => "E0573",
-            (PathSource::Type, false) => "E0412",
-            (PathSource::Struct, true) => "E0574",
-            (PathSource::Struct, false) => "E0422",
-            (PathSource::Expr(..), true) => "E0423",
-            (PathSource::Expr(..), false) => "E0425",
-            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
-            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
-            (PathSource::TraitItem(..), true) => "E0575",
-            (PathSource::TraitItem(..), false) => "E0576",
+            (PathSource::Trait(_), true) => error_code!(E0404),
+            (PathSource::Trait(_), false) => error_code!(E0405),
+            (PathSource::Type, true) => error_code!(E0573),
+            (PathSource::Type, false) => error_code!(E0412),
+            (PathSource::Struct, true) => error_code!(E0574),
+            (PathSource::Struct, false) => error_code!(E0422),
+            (PathSource::Expr(..), true) => error_code!(E0423),
+            (PathSource::Expr(..), false) => error_code!(E0425),
+            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => error_code!(E0532),
+            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => error_code!(E0531),
+            (PathSource::TraitItem(..), true) => error_code!(E0575),
+            (PathSource::TraitItem(..), false) => error_code!(E0576),
         }
     }
 }
@@ -807,14 +795,14 @@
                 self.resolve_adt(item, generics);
             }
 
-            ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
-                self.resolve_implementation(
-                    generics,
-                    opt_trait_ref,
-                    &self_type,
-                    item.id,
-                    impl_items,
-                )
+            ItemKind::Impl {
+                ref generics,
+                ref of_trait,
+                ref self_ty,
+                items: ref impl_items,
+                ..
+            } => {
+                self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
             }
 
             ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 5a12a75..6a98c9e 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -4,10 +4,9 @@
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
-use log::debug;
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
@@ -18,7 +17,7 @@
 use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind};
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
+use log::debug;
 
 type Res = def::Res<ast::NodeId>;
 
@@ -73,7 +72,6 @@
         let expected = source.descr_expected();
         let path_str = Segment::names_to_string(path);
         let item_str = path.last().unwrap().ident;
-        let code = source.error_code(res.is_some());
         let (base_msg, fallback_label, base_span, could_be_expr) = if let Some(res) = res {
             (
                 format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
@@ -123,7 +121,7 @@
             )
         };
 
-        let code = DiagnosticId::Error(code.into());
+        let code = source.error_code(res.is_some());
         let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
 
         // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
@@ -140,8 +138,7 @@
 
         // Emit special messages for unresolved `Self` and `self`.
         if is_self_type(path, ns) {
-            syntax::diagnostic_used!(E0411);
-            err.code(DiagnosticId::Error("E0411".into()));
+            err.code(rustc_errors::error_code!(E0411));
             err.span_label(
                 span,
                 format!("`Self` is only available in impls, traits, and type definitions"),
@@ -151,8 +148,7 @@
         if is_self_value(path, ns) {
             debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
 
-            syntax::diagnostic_used!(E0424);
-            err.code(DiagnosticId::Error("E0424".into()));
+            err.code(rustc_errors::error_code!(E0424));
             err.span_label(span, match source {
                 PathSource::Pat => format!(
                     "`self` value is a keyword and may not be bound to variables or shadowed",
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 199752b..0e6f40f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2,44 +2,43 @@
 //!
 //! Module structure of the crate is built here.
 //! Paths in macros, imports, expressions, types, patterns are resolved here.
-//! Label names are resolved here as well.
+//! Label and lifetime names are resolved here as well.
 //!
 //! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`.
-//! Lifetime names are resolved in `librustc/middle/resolve_lifetime.rs`.
-
-// ignore-tidy-filelength
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(nll)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![recursion_limit = "256"]
 
 pub use rustc_hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
 
-use errors::{Applicability, DiagnosticBuilder};
 use rustc::hir::exports::ExportMap;
-use rustc::hir::map::Definitions;
+use rustc::hir::map::{DefKey, Definitions};
 use rustc::lint;
 use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
-use rustc::session::Session;
 use rustc::span_bug;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, DefIdTree, ResolverOutputs};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def::Namespace::*;
-use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
+use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
 use rustc_hir::{GlobMap, TraitMap};
 use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::node_id::{NodeMap, NodeSet};
+use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym};
@@ -49,8 +48,8 @@
 use syntax::ast::{ItemKind, Path};
 use syntax::attr;
 use syntax::print::pprust;
+use syntax::unwrap_or;
 use syntax::visit::{self, Visitor};
-use syntax::{struct_span_err, unwrap_or};
 
 use log::debug;
 use std::cell::{Cell, RefCell};
@@ -63,8 +62,6 @@
 use late::{HasGenericParams, PathSource, Rib, RibKind::*};
 use macros::{LegacyBinding, LegacyScope};
 
-use rustc_error_codes::*;
-
 type Res = def::Res<NodeId>;
 
 mod build_reduced_graph;
@@ -603,7 +600,11 @@
     }
 }
 
-struct PrivacyError<'a>(Span, Ident, &'a NameBinding<'a>);
+struct PrivacyError<'a> {
+    ident: Ident,
+    binding: &'a NameBinding<'a>,
+    dedup_span: Span,
+}
 
 struct UseError<'a> {
     err: DiagnosticBuilder<'a>,
@@ -960,7 +961,7 @@
     /// when visiting the correspondent variants.
     variant_vis: DefIdMap<ty::Visibility>,
 
-    lint_buffer: lint::LintBuffer,
+    lint_buffer: LintBuffer,
 
     next_node_id: NodeId,
 }
@@ -1027,8 +1028,12 @@
 /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
 /// the resolver is no longer needed as all the relevant information is inline.
 impl rustc_ast_lowering::Resolver for Resolver<'_> {
-    fn cstore(&self) -> &dyn CrateStore {
-        self.cstore()
+    fn def_key(&mut self, id: DefId) -> DefKey {
+        if id.is_local() { self.definitions().def_key(id.index) } else { self.cstore().def_key(id) }
+    }
+
+    fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
+        self.cstore().item_generics_num_lifetimes(def_id, sess)
     }
 
     fn resolve_str_path(
@@ -1078,7 +1083,7 @@
         &mut self.definitions
     }
 
-    fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
+    fn lint_buffer(&mut self) -> &mut LintBuffer {
         &mut self.lint_buffer
     }
 
@@ -1237,7 +1242,7 @@
                 .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
                 .collect(),
             variant_vis: Default::default(),
-            lint_buffer: lint::LintBuffer::default(),
+            lint_buffer: LintBuffer::default(),
             next_node_id: NodeId::from_u32(1),
         }
     }
@@ -1252,7 +1257,7 @@
         self.next_node_id
     }
 
-    pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
+    pub fn lint_buffer(&mut self) -> &mut LintBuffer {
         &mut self.lint_buffer
     }
 
@@ -1709,10 +1714,10 @@
                     if let Some(node_id) = poisoned {
                         self.lint_buffer.buffer_lint_with_diagnostic(
                             lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-                            node_id, ident.span,
+                            node_id,
+                            ident.span,
                             &format!("cannot find {} `{}` in this scope", ns.descr(), ident),
-                            lint::builtin::BuiltinLintDiagnostics::
-                                ProcMacroDeriveResolutionFallback(ident.span),
+                            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(ident.span),
                         );
                     }
                     return Some(LexicalScopeBinding::Item(binding));
@@ -2001,7 +2006,7 @@
                             continue;
                         }
                     }
-                    let msg = "there are too many initial `super`s.".to_string();
+                    let msg = "there are too many leading `super` keywords".to_string();
                     return PathResult::Failed {
                         span: ident.span,
                         label: msg,
@@ -2263,7 +2268,7 @@
             }
         }
 
-        let diag = lint::builtin::BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
+        let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
         self.lint_buffer.buffer_lint_with_diagnostic(
             lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             diag_id,
@@ -2441,115 +2446,6 @@
         }
     }
 
-    fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
-        let res = b.res();
-        if b.span.is_dummy() {
-            let add_built_in = match b.res() {
-                // These already contain the "built-in" prefix or look bad with it.
-                Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => false,
-                _ => true,
-            };
-            let (built_in, from) = if from_prelude {
-                ("", " from prelude")
-            } else if b.is_extern_crate()
-                && !b.is_import()
-                && self.session.opts.externs.get(&ident.as_str()).is_some()
-            {
-                ("", " passed with `--extern`")
-            } else if add_built_in {
-                (" built-in", "")
-            } else {
-                ("", "")
-            };
-
-            let article = if built_in.is_empty() { res.article() } else { "a" };
-            format!(
-                "{a}{built_in} {thing}{from}",
-                a = article,
-                thing = res.descr(),
-                built_in = built_in,
-                from = from
-            )
-        } else {
-            let introduced = if b.is_import() { "imported" } else { "defined" };
-            format!("the {thing} {introduced} here", thing = res.descr(), introduced = introduced)
-        }
-    }
-
-    fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
-        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
-        let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
-            // We have to print the span-less alternative first, otherwise formatting looks bad.
-            (b2, b1, misc2, misc1, true)
-        } else {
-            (b1, b2, misc1, misc2, false)
-        };
-
-        let mut err = struct_span_err!(
-            self.session,
-            ident.span,
-            E0659,
-            "`{ident}` is ambiguous ({why})",
-            ident = ident,
-            why = kind.descr()
-        );
-        err.span_label(ident.span, "ambiguous name");
-
-        let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
-            let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
-            let note_msg = format!(
-                "`{ident}` could{also} refer to {what}",
-                ident = ident,
-                also = also,
-                what = what
-            );
-
-            let thing = b.res().descr();
-            let mut help_msgs = Vec::new();
-            if b.is_glob_import()
-                && (kind == AmbiguityKind::GlobVsGlob
-                    || kind == AmbiguityKind::GlobVsExpanded
-                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
-            {
-                help_msgs.push(format!(
-                    "consider adding an explicit import of \
-                     `{ident}` to disambiguate",
-                    ident = ident
-                ))
-            }
-            if b.is_extern_crate() && ident.span.rust_2018() {
-                help_msgs.push(format!(
-                    "use `::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            }
-            if misc == AmbiguityErrorMisc::SuggestCrate {
-                help_msgs.push(format!(
-                    "use `crate::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            } else if misc == AmbiguityErrorMisc::SuggestSelf {
-                help_msgs.push(format!(
-                    "use `self::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            }
-
-            err.span_note(b.span, &note_msg);
-            for (i, help_msg) in help_msgs.iter().enumerate() {
-                let or = if i == 0 { "" } else { "or " };
-                err.help(&format!("{}{}", or, help_msg));
-            }
-        };
-
-        could_refer_to(b1, misc1, "");
-        could_refer_to(b2, misc2, " also");
-        err.emit();
-    }
-
     fn report_errors(&mut self, krate: &Crate) {
         self.report_with_use_injections(krate);
 
@@ -2558,9 +2454,10 @@
                        cannot be referred to by absolute paths";
             self.lint_buffer.buffer_lint_with_diagnostic(
                 lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
-                CRATE_NODE_ID, span_use, msg,
-                lint::builtin::BuiltinLintDiagnostics::
-                    MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+                CRATE_NODE_ID,
+                span_use,
+                msg,
+                BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
             );
         }
 
@@ -2569,43 +2466,9 @@
         }
 
         let mut reported_spans = FxHashSet::default();
-        for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors {
-            if reported_spans.insert(dedup_span) {
-                let session = &self.session;
-                let mk_struct_span_error = |is_constructor| {
-                    struct_span_err!(
-                        session,
-                        ident.span,
-                        E0603,
-                        "{}{} `{}` is private",
-                        binding.res().descr(),
-                        if is_constructor { " constructor" } else { "" },
-                        ident.name,
-                    )
-                };
-
-                let mut err = if let NameBindingKind::Res(
-                    Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
-                    _,
-                ) = binding.kind
-                {
-                    let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
-                    if let Some(fields) = self.field_names.get(&def_id) {
-                        let mut err = mk_struct_span_error(true);
-                        let first_field = fields.first().expect("empty field list in the map");
-                        err.span_label(
-                            fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
-                            "a constructor is private if any of the fields is private",
-                        );
-                        err
-                    } else {
-                        mk_struct_span_error(false)
-                    }
-                } else {
-                    mk_struct_span_error(false)
-                };
-
-                err.emit();
+        for error in &self.privacy_errors {
+            if reported_spans.insert(error.dedup_span) {
+                self.report_privacy_error(error);
             }
         }
     }
diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs
index 4cd3a9e..6e9ed5f 100644
--- a/src/librustc_resolve/lifetimes.rs
+++ b/src/librustc_resolve/lifetimes.rs
@@ -5,18 +5,20 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use crate::diagnostics::{
+    add_missing_lifetime_specifiers_label, report_missing_lifetime_specifiers,
+};
 use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
-use rustc::session::Session;
 use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
 use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
 use rustc_span::symbol::{kw, sym};
@@ -26,12 +28,10 @@
 use std::mem::{replace, take};
 use syntax::ast;
 use syntax::attr;
-use syntax::{help, span_err, struct_span_err, walk_list};
+use syntax::walk_list;
 
 use log::debug;
 
-use rustc_error_codes::*;
-
 // This counts the no of times a lifetime is used
 #[derive(Clone, Copy, Debug)]
 pub enum LifetimeUseSet<'tcx> {
@@ -183,6 +183,10 @@
     xcrate_object_lifetime_defaults: DefIdMap<Vec<ObjectLifetimeDefault>>,
 
     lifetime_uses: &'a mut DefIdMap<LifetimeUseSet<'tcx>>,
+
+    /// When encountering an undefined named lifetime, we will suggest introducing it in these
+    /// places.
+    missing_named_lifetime_spots: Vec<&'tcx hir::Generics<'tcx>>,
 }
 
 #[derive(Debug)]
@@ -342,6 +346,7 @@
             labels_in_fn: vec![],
             xcrate_object_lifetime_defaults: Default::default(),
             lifetime_uses: &mut Default::default(),
+            missing_named_lifetime_spots: vec![],
         };
         for (_, item) in &krate.items {
             visitor.visit_item(item);
@@ -361,7 +366,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::All(&self.tcx.hir())
     }
 
@@ -382,9 +389,11 @@
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         match item.kind {
             hir::ItemKind::Fn(ref sig, ref generics, _) => {
+                self.missing_named_lifetime_spots.push(generics);
                 self.visit_early_late(None, &sig.decl, generics, |this| {
                     intravisit::walk_item(this, item);
                 });
+                self.missing_named_lifetime_spots.pop();
             }
 
             hir::ItemKind::ExternCrate(_)
@@ -414,11 +423,13 @@
             | hir::ItemKind::Union(_, ref generics)
             | hir::ItemKind::Trait(_, _, ref generics, ..)
             | hir::ItemKind::TraitAlias(ref generics, ..)
-            | hir::ItemKind::Impl(_, _, _, ref generics, ..) => {
+            | hir::ItemKind::Impl { ref generics, .. } => {
+                self.missing_named_lifetime_spots.push(generics);
+
                 // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name".
                 // This is not true for other kinds of items.x
                 let track_lifetime_uses = match item.kind {
-                    hir::ItemKind::Impl(..) => true,
+                    hir::ItemKind::Impl { .. } => true,
                     _ => false,
                 };
                 // These kinds of items have only early-bound lifetime parameters.
@@ -452,6 +463,7 @@
                     this.check_lifetime_params(old_scope, &generics.params);
                     intravisit::walk_item(this, item);
                 });
+                self.missing_named_lifetime_spots.pop();
             }
         }
     }
@@ -591,13 +603,14 @@
                                     || krate.impl_items.contains_key(&parent_impl_id)
                                     || krate.trait_items.contains_key(&parent_trait_id))
                                 {
-                                    span_err!(
+                                    struct_span_err!(
                                         self.tcx.sess,
                                         lifetime.span,
                                         E0657,
                                         "`impl Trait` can only capture lifetimes \
                                          bound at the fn or impl level"
-                                    );
+                                    )
+                                    .emit();
                                     self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                                 }
                             }
@@ -683,6 +696,7 @@
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
+        self.missing_named_lifetime_spots.push(&trait_item.generics);
         match trait_item.kind {
             Method(ref sig, _) => {
                 let tcx = self.tcx;
@@ -734,10 +748,12 @@
                 intravisit::walk_trait_item(self, trait_item);
             }
         }
+        self.missing_named_lifetime_spots.pop();
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         use self::hir::ImplItemKind::*;
+        self.missing_named_lifetime_spots.push(&impl_item.generics);
         match impl_item.kind {
             Method(ref sig, _) => {
                 let tcx = self.tcx;
@@ -821,6 +837,7 @@
                 intravisit::walk_impl_item(self, impl_item);
             }
         }
+        self.missing_named_lifetime_spots.pop();
     }
 
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
@@ -943,12 +960,13 @@
             })
         {
             if self.trait_ref_hack {
-                span_err!(
+                struct_span_err!(
                     self.tcx.sess,
                     trait_ref.span,
                     E0316,
                     "nested quantification of lifetimes"
-                );
+                )
+                .emit();
             }
             let next_early_index = self.next_early_index();
             let scope = Scope::Binder {
@@ -1084,7 +1102,9 @@
     gather.visit_body(body);
 
     impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -1303,6 +1323,7 @@
         let LifetimeContext { tcx, map, lifetime_uses, .. } = self;
         let labels_in_fn = take(&mut self.labels_in_fn);
         let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults);
+        let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots);
         let mut this = LifetimeContext {
             tcx: *tcx,
             map: map,
@@ -1311,7 +1332,8 @@
             is_in_fn_syntax: self.is_in_fn_syntax,
             labels_in_fn,
             xcrate_object_lifetime_defaults,
-            lifetime_uses: lifetime_uses,
+            lifetime_uses,
+            missing_named_lifetime_spots,
         };
         debug!("entering scope {:?}", this.scope);
         f(self.scope, &mut this);
@@ -1319,6 +1341,7 @@
         debug!("exiting scope {:?}", this.scope);
         self.labels_in_fn = this.labels_in_fn;
         self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
+        self.missing_named_lifetime_spots = this.missing_named_lifetime_spots;
     }
 
     /// helper method to determine the span to remove when suggesting the
@@ -1632,7 +1655,7 @@
             }
             match parent.kind {
                 hir::ItemKind::Trait(_, _, ref generics, ..)
-                | hir::ItemKind::Impl(_, _, _, ref generics, ..) => {
+                | hir::ItemKind::Impl { ref generics, .. } => {
                     index += generics.params.len() as u32;
                 }
                 _ => {}
@@ -1801,15 +1824,29 @@
 
             self.insert_lifetime(lifetime_ref, def);
         } else {
-            struct_span_err!(
+            let mut err = struct_span_err!(
                 self.tcx.sess,
                 lifetime_ref.span,
                 E0261,
                 "use of undeclared lifetime name `{}`",
                 lifetime_ref
-            )
-            .span_label(lifetime_ref.span, "undeclared lifetime")
-            .emit();
+            );
+            err.span_label(lifetime_ref.span, "undeclared lifetime");
+            if !self.is_in_fn_syntax {
+                for generics in &self.missing_named_lifetime_spots {
+                    let (span, sugg) = match &generics.params {
+                        [] => (generics.span, format!("<{}>", lifetime_ref)),
+                        [param, ..] => (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)),
+                    };
+                    err.span_suggestion(
+                        span,
+                        &format!("consider introducing lifetime `{}` here", lifetime_ref),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+            err.emit();
         }
     }
 
@@ -2061,12 +2098,12 @@
             }
 
             Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => {
-                if let hir::ItemKind::Impl(.., ref self_ty, ref impl_items) =
+                if let hir::ItemKind::Impl { ref self_ty, ref items, .. } =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
                     impl_self = Some(self_ty);
                     assoc_item_kind =
-                        impl_items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind);
+                        items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind);
                 }
                 Some(body)
             }
@@ -2127,7 +2164,9 @@
             }
 
             impl<'a> Visitor<'a> for SelfVisitor<'a> {
-                fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
+                type Map = Map<'a>;
+
+                fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
                     NestedVisitorMap::None
                 }
 
@@ -2215,7 +2254,9 @@
         }
 
         impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> {
-            fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+            type Map = Map<'v>;
+
+            fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
                 NestedVisitorMap::None
             }
 
@@ -2359,6 +2400,7 @@
                 lifetime_refs.len(),
                 &lifetime_names,
                 self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
+                &self.missing_named_lifetime_spots,
             );
         }
 
@@ -2433,36 +2475,32 @@
         }
 
         if len == 0 {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 there is no value for it to be borrowed from"
+            db.help(
+                "this function's return type contains a borrowed value, \
+                but there is no value for it to be borrowed from",
             );
             self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
         } else if elided_len == 0 {
-            help!(
-                db,
+            db.help(
                 "this function's return type contains a borrowed value with \
                  an elided lifetime, but the lifetime cannot be derived from \
-                 the arguments"
+                 the arguments",
             );
             let msg = "consider giving it an explicit bounded or 'static lifetime";
             self.suggest_lifetime(db, span, msg)
         } else if elided_len == 1 {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 the signature does not say which {} it is borrowed from",
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                but the signature does not say which {} it is borrowed from",
                 m
-            );
+            ));
             true
         } else {
-            help!(
-                db,
-                "this function's return type contains a borrowed value, but \
-                 the signature does not say whether it is borrowed from {}",
+            db.help(&format!(
+                "this function's return type contains a borrowed value, \
+                but the signature does not say whether it is borrowed from {}",
                 m
-            );
+            ));
             true
         }
     }
@@ -2804,7 +2842,9 @@
     }
 
     impl<'v> Visitor<'v> for ConstrainedCollector {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -2845,7 +2885,9 @@
     }
 
     impl<'v> Visitor<'v> for AllCollector {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+        type Map = Map<'v>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -2854,34 +2896,3 @@
         }
     }
 }
-
-fn report_missing_lifetime_specifiers(
-    sess: &Session,
-    span: Span,
-    count: usize,
-) -> DiagnosticBuilder<'_> {
-    struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count))
-}
-
-fn add_missing_lifetime_specifiers_label(
-    err: &mut DiagnosticBuilder<'_>,
-    span: Span,
-    count: usize,
-    lifetime_names: &FxHashSet<ast::Ident>,
-    snippet: Option<&str>,
-) {
-    if count > 1 {
-        err.span_label(span, format!("expected {} lifetime parameters", count));
-    } else if let (1, Some(name), Some("&")) =
-        (lifetime_names.len(), lifetime_names.iter().next(), snippet)
-    {
-        err.span_suggestion(
-            span,
-            "consider using the named lifetime",
-            format!("&{} ", name),
-            Applicability::MaybeIncorrect,
-        );
-    } else {
-        err.span_label(span, "expected lifetime parameter");
-    }
-}
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 1103d5b..85b5d8e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -7,6 +7,7 @@
 use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
 use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
 use rustc::middle::stability;
+use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::{lint, span_bug, ty};
 use rustc_data_structures::fx::FxHashSet;
@@ -23,7 +24,6 @@
 use rustc_span::{Span, DUMMY_SP};
 use syntax::ast::{self, Ident, NodeId};
 use syntax::attr::{self, StabilityLevel};
-use syntax::feature_gate::feature_err;
 use syntax::print::pprust;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 2f2ba56..d252fc5 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1300,8 +1300,8 @@
                 self.process_struct(item, def, ty_params)
             }
             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            Impl(.., ref ty_params, ref trait_ref, ref typ, ref impl_items) => {
-                self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
+            Impl { ref generics, ref of_trait, ref self_ty, ref items, .. } => {
+                self.process_impl(item, generics, of_trait, &self_ty, items)
             }
             Trait(_, _, ref generics, ref trait_refs, ref methods) => {
                 self.process_trait(item, generics, trait_refs, methods)
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index c3221d9..537fe19 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -305,8 +305,8 @@
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ItemKind::Impl(.., ref trait_ref, ref typ, ref impls) => {
-                if let ast::TyKind::Path(None, ref path) = typ.kind {
+            ast::ItemKind::Impl { ref of_trait, ref self_ty, ref items, .. } => {
+                if let ast::TyKind::Path(None, ref path) = self_ty.kind {
                     // Common case impl for a struct or something basic.
                     if generated_code(path.span) {
                         return None;
@@ -317,14 +317,14 @@
                     let impl_id = self.next_impl_id();
                     let span = self.span_from_span(sub_span);
 
-                    let type_data = self.lookup_def_id(typ.id);
+                    let type_data = self.lookup_def_id(self_ty.id);
                     type_data.map(|type_data| {
                         Data::RelationData(
                             Relation {
                                 kind: RelationKind::Impl { id: impl_id },
                                 span: span.clone(),
                                 from: id_from_def_id(type_data),
-                                to: trait_ref
+                                to: of_trait
                                     .as_ref()
                                     .and_then(|t| self.lookup_def_id(t.ref_id))
                                     .map(id_from_def_id)
@@ -332,14 +332,14 @@
                             },
                             Impl {
                                 id: impl_id,
-                                kind: match *trait_ref {
+                                kind: match *of_trait {
                                     Some(_) => ImplKind::Direct,
                                     None => ImplKind::Inherent,
                                 },
                                 span: span,
                                 value: String::new(),
                                 parent: None,
-                                children: impls
+                                children: items
                                     .iter()
                                     .map(|i| id_from_node_id(i.id, self))
                                     .collect(),
@@ -405,9 +405,9 @@
         {
             Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
                 Some(Node::Item(item)) => match item.kind {
-                    hir::ItemKind::Impl(.., ref ty, _) => {
+                    hir::ItemKind::Impl { ref self_ty, .. } => {
                         let mut qualname = String::from("<");
-                        qualname.push_str(&self.tcx.hir().hir_to_pretty_string(ty.hir_id));
+                        qualname.push_str(&self.tcx.hir().hir_to_pretty_string(self_ty.hir_id));
 
                         let trait_id = self.tcx.trait_id_of_impl(impl_id);
                         let mut decl_id = None;
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index e7b86cf..a9d2bfa 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -482,15 +482,16 @@
 
                 Ok(sig)
             }
-            ast::ItemKind::Impl(
+            ast::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
+                constness,
                 ref generics,
-                ref opt_trait,
-                ref ty,
-                _,
-            ) => {
+                ref of_trait,
+                ref self_ty,
+                items: _,
+            } => {
                 let mut text = String::new();
                 if let ast::Defaultness::Default = defaultness {
                     text.push_str("default ");
@@ -499,13 +500,16 @@
                     text.push_str("unsafe ");
                 }
                 text.push_str("impl");
+                if constness == ast::Constness::Const {
+                    text.push_str(" const");
+                }
 
                 let generics_sig = generics.make(offset + text.len(), id, scx)?;
                 text.push_str(&generics_sig.text);
 
                 text.push(' ');
 
-                let trait_sig = if let Some(ref t) = *opt_trait {
+                let trait_sig = if let Some(ref t) = *of_trait {
                     if polarity == ast::ImplPolarity::Negative {
                         text.push('!');
                     }
@@ -517,7 +521,7 @@
                     text_sig(String::new())
                 };
 
-                let ty_sig = ty.make(offset + text.len(), id, scx)?;
+                let ty_sig = self_ty.make(offset + text.len(), id, scx)?;
                 text.push_str(&ty_sig.text);
 
                 text.push_str(" {}");
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index b6b22e2..aa492b5 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -447,9 +447,8 @@
 #[derive(Clone, Hash)]
 pub struct OutputFilenames {
     pub out_directory: PathBuf,
-    pub out_filestem: String,
+    filestem: String,
     pub single_output_file: Option<PathBuf>,
-    pub extra: String,
     pub outputs: OutputTypes,
 }
 
@@ -458,6 +457,21 @@
 pub const RUST_CGU_EXT: &str = "rcgu";
 
 impl OutputFilenames {
+    pub fn new(
+        out_directory: PathBuf,
+        out_filestem: String,
+        single_output_file: Option<PathBuf>,
+        extra: String,
+        outputs: OutputTypes,
+    ) -> Self {
+        OutputFilenames {
+            out_directory,
+            single_output_file,
+            outputs,
+            filestem: format!("{}{}", out_filestem, extra),
+        }
+    }
+
     pub fn path(&self, flavor: OutputType) -> PathBuf {
         self.outputs
             .get(&flavor)
@@ -477,8 +491,6 @@
     /// Like temp_path, but also supports things where there is no corresponding
     /// OutputType, like noopt-bitcode or lto-bitcode.
     pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf {
-        let base = self.out_directory.join(&self.filestem());
-
         let mut extension = String::new();
 
         if let Some(codegen_unit_name) = codegen_unit_name {
@@ -495,16 +507,13 @@
             extension.push_str(ext);
         }
 
-        let path = base.with_extension(&extension[..]);
-        path
+        self.with_extension(&extension)
     }
 
     pub fn with_extension(&self, extension: &str) -> PathBuf {
-        self.out_directory.join(&self.filestem()).with_extension(extension)
-    }
-
-    pub fn filestem(&self) -> String {
-        format!("{}{}", self.out_filestem, self.extra)
+        let mut path = self.out_directory.join(&self.filestem);
+        path.set_extension(extension);
+        path
     }
 }
 
@@ -619,7 +628,7 @@
 
 impl_stable_hash_via_hash!(EntryFnType);
 
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum CrateType {
     Executable,
     Dylib,
diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs
index 0cce7e8..2ba3932 100644
--- a/src/librustc_session/lint.rs
+++ b/src/librustc_session/lint.rs
@@ -1,8 +1,10 @@
 pub use self::Level::*;
-use crate::node_id::NodeId;
+use crate::node_id::{NodeId, NodeMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_span::edition::Edition;
-use rustc_span::{sym, MultiSpan, Symbol};
+use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
+
+pub mod builtin;
 
 /// Setting for how to handle a lint.
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
@@ -174,7 +176,25 @@
     }
 }
 
-/// Stores buffered lint info which can later be passed to `librustc`.
+// This could be a closure, but then implementing derive trait
+// becomes hacky (and it gets allocated).
+#[derive(PartialEq)]
+pub enum BuiltinLintDiagnostics {
+    Normal,
+    BareTraitObject(Span, /* is_global */ bool),
+    AbsPathWithModule(Span),
+    ProcMacroDeriveResolutionFallback(Span),
+    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
+    ElidedLifetimesInPaths(usize, Span, bool, Span, String),
+    UnknownCrateTypes(Span, String, String),
+    UnusedImports(String, Vec<(Span, String)>),
+    RedundantImport(Vec<(Span, bool)>, Ident),
+    DeprecatedMacro(Option<Symbol>, Span),
+}
+
+/// Lints that are buffered up early on in the `Session` before the
+/// `LintLevels` is calculated. These are later passed to `librustc`.
+#[derive(PartialEq)]
 pub struct BufferedEarlyLint {
     /// The span of code that we are linting on.
     pub span: MultiSpan,
@@ -183,10 +203,65 @@
     pub msg: String,
 
     /// The `NodeId` of the AST node that generated the lint.
-    pub id: NodeId,
+    pub node_id: NodeId,
 
     /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
-    pub lint_id: &'static Lint,
+    pub lint_id: LintId,
+
+    /// Customization of the `DiagnosticBuilder<'_>` for the lint.
+    pub diagnostic: BuiltinLintDiagnostics,
+}
+
+#[derive(Default)]
+pub struct LintBuffer {
+    pub map: NodeMap<Vec<BufferedEarlyLint>>,
+}
+
+impl LintBuffer {
+    pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
+        let arr = self.map.entry(early_lint.node_id).or_default();
+        if !arr.contains(&early_lint) {
+            arr.push(early_lint);
+        }
+    }
+
+    pub fn add_lint(
+        &mut self,
+        lint: &'static Lint,
+        node_id: NodeId,
+        span: MultiSpan,
+        msg: &str,
+        diagnostic: BuiltinLintDiagnostics,
+    ) {
+        let lint_id = LintId::of(lint);
+        let msg = msg.to_string();
+        self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
+    }
+
+    pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
+        self.map.remove(&id).unwrap_or_default()
+    }
+
+    pub fn buffer_lint(
+        &mut self,
+        lint: &'static Lint,
+        id: NodeId,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+    ) {
+        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
+    }
+
+    pub fn buffer_lint_with_diagnostic(
+        &mut self,
+        lint: &'static Lint,
+        id: NodeId,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+        diagnostic: BuiltinLintDiagnostics,
+    ) {
+        self.add_lint(lint, id, sp.into(), msg, diagnostic)
+    }
 }
 
 /// Declares a static item of type `&'static Lint`.
@@ -253,3 +328,41 @@
         };
     );
 }
+
+/// Declares a static `LintArray` and return it as an expression.
+#[macro_export]
+macro_rules! lint_array {
+    ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
+    ($( $lint:expr ),*) => {{
+        vec![$($lint),*]
+    }}
+}
+
+pub type LintArray = Vec<&'static Lint>;
+
+pub trait LintPass {
+    fn name(&self) -> &'static str;
+}
+
+/// Implements `LintPass for $name` with the given list of `Lint` statics.
+#[macro_export]
+macro_rules! impl_lint_pass {
+    ($name:ident => [$($lint:expr),* $(,)?]) => {
+        impl $crate::lint::LintPass for $name {
+            fn name(&self) -> &'static str { stringify!($name) }
+        }
+        impl $name {
+            pub fn get_lints() -> $crate::lint::LintArray { $crate::lint_array!($($lint),*) }
+        }
+    };
+}
+
+/// Declares a type named `$name` which implements `LintPass`.
+/// To the right of `=>` a comma separated list of `Lint` statics is given.
+#[macro_export]
+macro_rules! declare_lint_pass {
+    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
+        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
+        $crate::impl_lint_pass!($name => [$($lint),*]);
+    };
+}
diff --git a/src/librustc/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
similarity index 66%
rename from src/librustc/lint/builtin.rs
rename to src/librustc_session/lint/builtin.rs
index 847c610..3e8503e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -4,16 +4,31 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::lint::{FutureIncompatibleInfo, LateLintPass, LintArray, LintPass};
-use crate::middle::stability;
-use crate::session::Session;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc_session::declare_lint;
+use crate::lint::FutureIncompatibleInfo;
+use crate::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
-use rustc_span::source_map::Span;
-use rustc_span::symbol::Symbol;
-use syntax::ast;
-use syntax::early_buffered_lints::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
+
+declare_lint! {
+    pub ILL_FORMED_ATTRIBUTE_INPUT,
+    Deny,
+    "ill-formed attribute inputs that were previously accepted and used in practice",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
+        edition: None,
+    };
+}
+
+declare_lint! {
+    pub META_VARIABLE_MISUSE,
+    Allow,
+    "possible meta-variable misuse at macro definition"
+}
+
+declare_lint! {
+    pub INCOMPLETE_INCLUDE,
+    Deny,
+    "trailing content in included file"
+}
 
 declare_lint! {
     pub EXCEEDING_BITSHIFTS,
@@ -96,6 +111,12 @@
 }
 
 declare_lint! {
+    pub BINDINGS_WITH_VARIANT_NAME,
+    Warn,
+    "detects pattern bindings with the same name as one of the matched variants"
+}
+
+declare_lint! {
     pub UNUSED_MACROS,
     Warn,
     "detects macros that were not used"
@@ -459,6 +480,7 @@
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
         OVERLAPPING_PATTERNS,
+        BINDINGS_WITH_VARIANT_NAME,
         UNUSED_MACROS,
         WARNINGS,
         UNUSED_FEATURES,
@@ -506,145 +528,3 @@
         SOFT_UNSTABLE,
     ]
 }
-
-// this could be a closure, but then implementing derive traits
-// becomes hacky (and it gets allocated)
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
-pub enum BuiltinLintDiagnostics {
-    Normal,
-    BareTraitObject(Span, /* is_global */ bool),
-    AbsPathWithModule(Span),
-    ProcMacroDeriveResolutionFallback(Span),
-    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
-    ElidedLifetimesInPaths(usize, Span, bool, Span, String),
-    UnknownCrateTypes(Span, String, String),
-    UnusedImports(String, Vec<(Span, String)>),
-    RedundantImport(Vec<(Span, bool)>, ast::Ident),
-    DeprecatedMacro(Option<Symbol>, Span),
-}
-
-pub fn add_elided_lifetime_in_path_suggestion(
-    sess: &Session,
-    db: &mut DiagnosticBuilder<'_>,
-    n: usize,
-    path_span: Span,
-    incl_angl_brckt: bool,
-    insertion_span: Span,
-    anon_lts: String,
-) {
-    let (replace_span, suggestion) = if incl_angl_brckt {
-        (insertion_span, anon_lts)
-    } else {
-        // When possible, prefer a suggestion that replaces the whole
-        // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
-        // at a point (which makes for an ugly/confusing label)
-        if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
-            // But our spans can get out of whack due to macros; if the place we think
-            // we want to insert `'_` isn't even within the path expression's span, we
-            // should bail out of making any suggestion rather than panicking on a
-            // subtract-with-overflow or string-slice-out-out-bounds (!)
-            // FIXME: can we do better?
-            if insertion_span.lo().0 < path_span.lo().0 {
-                return;
-            }
-            let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
-            if insertion_index > snippet.len() {
-                return;
-            }
-            let (before, after) = snippet.split_at(insertion_index);
-            (path_span, format!("{}{}{}", before, anon_lts, after))
-        } else {
-            (insertion_span, anon_lts)
-        }
-    };
-    db.span_suggestion(
-        replace_span,
-        &format!("indicate the anonymous lifetime{}", pluralize!(n)),
-        suggestion,
-        Applicability::MachineApplicable,
-    );
-}
-
-impl BuiltinLintDiagnostics {
-    pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
-        match self {
-            BuiltinLintDiagnostics::Normal => (),
-            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
-                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
-                    Ok(ref s) if is_global => {
-                        (format!("dyn ({})", s), Applicability::MachineApplicable)
-                    }
-                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
-                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
-                };
-                db.span_suggestion(span, "use `dyn`", sugg, app);
-            }
-            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
-                let (sugg, app) = match sess.source_map().span_to_snippet(span) {
-                    Ok(ref s) => {
-                        // FIXME(Manishearth) ideally the emitting code
-                        // can tell us whether or not this is global
-                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
-
-                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
-                    }
-                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
-                };
-                db.span_suggestion(span, "use `crate`", sugg, app);
-            }
-            BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
-                db.span_label(
-                    span,
-                    "names from parent modules are not \
-                                     accessible without an explicit import",
-                );
-            }
-            BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
-                db.span_note(span_def, "the macro is defined here");
-            }
-            BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-                n,
-                path_span,
-                incl_angl_brckt,
-                insertion_span,
-                anon_lts,
-            ) => {
-                add_elided_lifetime_in_path_suggestion(
-                    sess,
-                    db,
-                    n,
-                    path_span,
-                    incl_angl_brckt,
-                    insertion_span,
-                    anon_lts,
-                );
-            }
-            BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
-                db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
-            }
-            BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
-                if !replaces.is_empty() {
-                    db.tool_only_multipart_suggestion(
-                        &message,
-                        replaces,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
-                for (span, is_imported) in spans {
-                    let introduced = if is_imported { "imported" } else { "defined" };
-                    db.span_label(
-                        span,
-                        format!("the item `{}` is already {} here", ident, introduced),
-                    );
-                }
-            }
-            BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
-                stability::deprecation_suggestion(db, suggestion, span)
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 656c1b0..34da218 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -772,8 +772,6 @@
         "set the current terminal width"),
     panic_abort_tests: bool = (false, parse_bool, [TRACKED],
         "support compiling tests with panic=abort"),
-    continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
-        "attempt to recover from parse errors (experimental)"),
     dep_tasks: bool = (false, parse_bool, [UNTRACKED],
         "print tasks that execute and the color their dep node gets (requires debug build)"),
     incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
@@ -925,8 +923,12 @@
     self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
         parse_switch_with_opt_path, [UNTRACKED],
         "run the self profiler and output the raw event data"),
+    // keep this in sync with the event filter names in librustc_data_structures/profiling.rs
     self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
-        "specifies which kinds of events get recorded by the self profiler"),
+        "specifies which kinds of events get recorded by the self profiler;
+        for example: `-Z self-profile-events=default,query-keys`
+        all options: none, all, default, generic-activity, query-provider, query-cache-hit
+                     query-blocked, incr-cache-load, query-keys"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
         "emits a section containing stack size metadata"),
     plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -948,4 +950,6 @@
          (such as entering an empty infinite loop) by inserting llvm.sideeffect"),
     deduplicate_diagnostics: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
         "deduplicate identical diagnostics"),
+    no_link: bool = (false, parse_bool, [TRACKED],
+        "compile without linking"),
 }
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 6cc6a1e..72c68fc 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -1,15 +1,14 @@
 //! Contains `ParseSess` which holds state living beyond what one `Parser` might.
 //! It also serves as an input to the parser itself.
 
-use crate::lint::BufferedEarlyLint;
+use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
 use crate::node_id::NodeId;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{Lock, Lrc, Once};
-use rustc_errors::{
-    emitter::SilentEmitter, Applicability, ColorConfig, DiagnosticBuilder, Handler,
-};
-use rustc_feature::UnstableFeatures;
+use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
+use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
+use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
@@ -62,6 +61,45 @@
     }
 }
 
+/// Construct a diagnostic for a language feature error due to the given `span`.
+/// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
+pub fn feature_err<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
+    feature_err_issue(sess, feature, span, GateIssue::Language, explain)
+}
+
+/// Construct a diagnostic for a feature gate error.
+///
+/// This variant allows you to control whether it is a library or language feature.
+/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
+pub fn feature_err_issue<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: impl Into<MultiSpan>,
+    issue: GateIssue,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
+    let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658));
+
+    if let Some(n) = find_feature_issue(feature, issue) {
+        err.note(&format!(
+            "for more information, see https://github.com/rust-lang/rust/issues/{}",
+            n,
+        ));
+    }
+
+    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
+    if sess.unstable_features.is_nightly_build() {
+        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
+    }
+
+    err
+}
+
 /// Info about a parsing session.
 pub struct ParseSess {
     pub span_diagnostic: Handler,
@@ -123,17 +161,18 @@
 
     pub fn buffer_lint(
         &self,
-        lint_id: &'static crate::lint::Lint,
+        lint: &'static Lint,
         span: impl Into<MultiSpan>,
-        id: NodeId,
+        node_id: NodeId,
         msg: &str,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
                 span: span.into(),
-                id,
+                node_id,
                 msg: msg.into(),
-                lint_id,
+                lint_id: LintId::of(lint),
+                diagnostic: BuiltinLintDiagnostics::Normal,
             });
         });
     }
diff --git a/src/librustc_session/search_paths.rs b/src/librustc_session/search_paths.rs
index b15f4e8..06f408b 100644
--- a/src/librustc_session/search_paths.rs
+++ b/src/librustc_session/search_paths.rs
@@ -9,7 +9,7 @@
     pub files: Vec<PathBuf>,
 }
 
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, RustcEncodable, RustcDecodable)]
 pub enum PathKind {
     Native,
     Crate,
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index dba5b9f..a40d645 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -1124,6 +1124,36 @@
                   See https://github.com/rust-lang/rust/issues/61002 for details.",
         );
     }
+
+    // Sanitizers can only be used on some tested platforms.
+    if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
+        const ASAN_SUPPORTED_TARGETS: &[&str] = &[
+            "x86_64-unknown-linux-gnu",
+            "x86_64-apple-darwin",
+            "x86_64-fuchsia",
+            "aarch64-fuchsia",
+        ];
+        const TSAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const LSAN_SUPPORTED_TARGETS: &[&str] =
+            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
+        const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
+
+        let supported_targets = match *sanitizer {
+            Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
+            Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
+            Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
+            Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
+        };
+
+        if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
+            sess.err(&format!(
+                "{:?}Sanitizer only works with the `{}` target",
+                sanitizer,
+                supported_targets.join("` or `")
+            ));
+        }
+    }
 }
 
 /// Hash value constructed out of all the `-C metadata` arguments passed to the
diff --git a/src/librustc_session/utils.rs b/src/librustc_session/utils.rs
index 7806f5e..fda11b6 100644
--- a/src/librustc_session/utils.rs
+++ b/src/librustc_session/utils.rs
@@ -2,11 +2,11 @@
 use rustc_data_structures::profiling::VerboseTimingGuard;
 
 impl Session {
-    pub fn timer<'a>(&'a self, what: &'a str) -> VerboseTimingGuard<'a> {
-        self.prof.sparse_pass(what)
+    pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
+        self.prof.verbose_generic_activity(what)
     }
-    pub fn time<R>(&self, what: &str, f: impl FnOnce() -> R) -> R {
-        self.prof.sparse_pass(what).run(f)
+    pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
+        self.prof.verbose_generic_activity(what).run(f)
     }
 }
 
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index 8cca59d..5779d17 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -5,7 +5,6 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![feature(const_fn)]
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
@@ -309,6 +308,11 @@
         self.ctxt() != SyntaxContext::root()
     }
 
+    /// Returns `true` if `span` originates in a derive-macro's expansion.
+    pub fn in_derive_expansion(self) -> bool {
+        matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
+    }
+
     #[inline]
     pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
         Span::new(lo, hi, SyntaxContext::root())
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index 0b9b9fe..e0b93b9 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -473,20 +473,23 @@
         lo.line != hi.line
     }
 
-    pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
-        debug!("span_to_lines(sp={:?})", sp);
-
+    pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
         let lo = self.lookup_char_pos(sp.lo());
         debug!("span_to_lines: lo={:?}", lo);
         let hi = self.lookup_char_pos(sp.hi());
         debug!("span_to_lines: hi={:?}", hi);
-
         if lo.file.start_pos != hi.file.start_pos {
             return Err(SpanLinesError::DistinctSources(DistinctSources {
                 begin: (lo.file.name.clone(), lo.file.start_pos),
                 end: (hi.file.name.clone(), hi.file.start_pos),
             }));
         }
+        Ok((lo, hi))
+    }
+
+    pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
+        debug!("span_to_lines(sp={:?})", sp);
+        let (lo, hi) = self.is_valid_span(sp)?;
         assert!(hi.line >= lo.line);
 
         let mut lines = Vec::with_capacity(hi.line - lo.line + 1);
@@ -499,14 +502,15 @@
         // and to the end of the line. Be careful because the line
         // numbers in Loc are 1-based, so we subtract 1 to get 0-based
         // lines.
-        for line_index in lo.line - 1..hi.line - 1 {
+        let hi_line = hi.line.saturating_sub(1);
+        for line_index in lo.line.saturating_sub(1)..hi_line {
             let line_len = lo.file.get_line(line_index).map(|s| s.chars().count()).unwrap_or(0);
             lines.push(LineInfo { line_index, start_col, end_col: CharPos::from_usize(line_len) });
             start_col = CharPos::from_usize(0);
         }
 
         // For the last line, it extends from `start_col` to `hi.col`:
-        lines.push(LineInfo { line_index: hi.line - 1, start_col, end_col: hi.col });
+        lines.push(LineInfo { line_index: hi_line, start_col, end_col: hi.col });
 
         Ok(FileLines { file: lo.file, lines })
     }
@@ -709,7 +713,7 @@
     pub fn next_point(&self, sp: Span) -> Span {
         let start_of_next_point = sp.hi().0;
 
-        let width = self.find_width_of_character_at_span(sp, true);
+        let width = self.find_width_of_character_at_span(sp.shrink_to_hi(), true);
         // If the width is 1, then the next span should point to the same `lo` and `hi`. However,
         // in the case of a multibyte character, where the width != 1, the next span should
         // span multiple bytes to include the whole character.
@@ -770,10 +774,10 @@
         // searching forwards for boundaries we've got somewhere to search.
         let snippet = if let Some(ref src) = local_begin.sf.src {
             let len = src.len();
-            (&src[start_index..len])
+            &src[start_index..len]
         } else if let Some(src) = src.get_source() {
             let len = src.len();
-            (&src[start_index..len])
+            &src[start_index..len]
         } else {
             return 1;
         };
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 40abc8b..e4f8b5a 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -167,6 +167,7 @@
         bindings_after_at,
         block,
         bool,
+        borrowck_graphviz_format,
         borrowck_graphviz_postflow,
         borrowck_graphviz_preflow,
         box_patterns,
@@ -219,6 +220,8 @@
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
         const_transmute,
+        const_trait_bound_opt_out,
+        const_trait_impl,
         contents,
         context,
         convert,
@@ -335,12 +338,14 @@
         FxHashSet,
         FxHashMap,
         gen_future,
+        gen_kill,
         generators,
         generic_associated_types,
         generic_param_attrs,
         global_allocator,
         global_asm,
         globs,
+        half_open_range_patterns,
         hash,
         Hash,
         HashSet,
@@ -732,6 +737,7 @@
         try_trait,
         tt,
         tuple_indexing,
+        two_phase,
         Ty,
         ty,
         type_alias_impl_trait,
@@ -1046,6 +1052,7 @@
 }
 
 // This module has a very short name because it's used a lot.
+#[allow(rustc::default_hash_types)]
 pub mod sym {
     use super::Symbol;
     use std::convert::TryInto;
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 17413e7..84c6d72 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -11,7 +11,7 @@
 #![feature(box_syntax)]
 #![feature(bool_to_option)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 #[macro_use]
 extern crate log;
diff --git a/src/librustc_target/spec/armv7a_none_eabi.rs b/src/librustc_target/spec/armv7a_none_eabi.rs
new file mode 100644
index 0000000..2fbef15
--- /dev/null
+++ b/src/librustc_target/spec/armv7a_none_eabi.rs
@@ -0,0 +1,48 @@
+// Generic ARMv7-A target for bare-metal code - floating point disabled
+//
+// This is basically the `armv7-unknown-linux-gnueabi` target with some changes
+// (listed below) to bring it closer to the bare-metal `thumb` & `aarch64`
+// targets:
+//
+// - `TargetOptions.features`: added `+strict-align`. rationale: unaligned
+// memory access is disabled on boot on these cores
+// - linker changed to LLD. rationale: C is not strictly needed to build
+// bare-metal binaries (the `gcc` linker has the advantage that it knows where C
+// libraries and crt*.o are but it's not much of an advantage here); LLD is also
+// faster
+// - `target_os` set to `none`. rationale: matches `thumb` targets
+// - `target_{env,vendor}` set to an empty string. rationale: matches `thumb`
+// targets
+// - `panic_strategy` set to `abort`. rationale: matches `thumb` targets
+// - `relocation-model` set to `static`; also no PIE, no relro and no dynamic
+// linking. rationale: matches `thumb` targets
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Result<Target, String> {
+    let opts = TargetOptions {
+        linker: Some("rust-lld".to_owned()),
+        features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(),
+        executables: true,
+        relocation_model: "static".to_string(),
+        disable_redzone: true,
+        max_atomic_width: Some(64),
+        panic_strategy: PanicStrategy::Abort,
+        abi_blacklist: super::arm_base::abi_blacklist(),
+        emit_debug_gdb_scripts: false,
+        ..Default::default()
+    };
+    Ok(Target {
+        llvm_target: "armv7a-none-eabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+        options: opts,
+    })
+}
diff --git a/src/librustc_target/spec/armv7a_none_eabihf.rs b/src/librustc_target/spec/armv7a_none_eabihf.rs
new file mode 100644
index 0000000..f31e68c
--- /dev/null
+++ b/src/librustc_target/spec/armv7a_none_eabihf.rs
@@ -0,0 +1,36 @@
+// Generic ARMv7-A target for bare-metal code - floating point enabled (assumes
+// FPU is present and emits FPU instructions)
+//
+// This is basically the `armv7-unknown-linux-gnueabihf` target with some
+// changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal
+// `thumb` & `aarch64` targets.
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Result<Target, String> {
+    let opts = TargetOptions {
+        linker: Some("rust-lld".to_owned()),
+        features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(),
+        executables: true,
+        relocation_model: "static".to_string(),
+        disable_redzone: true,
+        max_atomic_width: Some(64),
+        panic_strategy: PanicStrategy::Abort,
+        abi_blacklist: super::arm_base::abi_blacklist(),
+        emit_debug_gdb_scripts: false,
+        ..Default::default()
+    };
+    Ok(Target {
+        llvm_target: "armv7a-none-eabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+        options: opts,
+    })
+}
diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs
index 51eb231..a6c1d24 100644
--- a/src/librustc_target/spec/i386_apple_ios.rs
+++ b/src/librustc_target/spec/i386_apple_ios.rs
@@ -8,7 +8,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(),
+        data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:128-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index 7dfb2ba..033b87b 100644
--- a/src/librustc_target/spec/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -20,7 +20,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(),
+        data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:128-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "macos".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_linux_android.rs b/src/librustc_target/spec/i686_linux_android.rs
index 3f73d24..79242f2 100644
--- a/src/librustc_target/spec/i686_linux_android.rs
+++ b/src/librustc_target/spec/i686_linux_android.rs
@@ -18,7 +18,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_pc_windows_gnu.rs b/src/librustc_target/spec/i686_pc_windows_gnu.rs
index 9056e07..35fbf87 100644
--- a/src/librustc_target/spec/i686_pc_windows_gnu.rs
+++ b/src/librustc_target/spec/i686_pc_windows_gnu.rs
@@ -18,7 +18,9 @@
         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(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/i686_pc_windows_msvc.rs b/src/librustc_target/spec/i686_pc_windows_msvc.rs
index b160007..ffb66af 100644
--- a/src/librustc_target/spec/i686_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/i686_pc_windows_msvc.rs
@@ -19,7 +19,9 @@
         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(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/i686_unknown_cloudabi.rs b/src/librustc_target/spec/i686_unknown_cloudabi.rs
index f3b4063..729b1f6 100644
--- a/src/librustc_target/spec/i686_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/i686_unknown_cloudabi.rs
@@ -13,7 +13,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "cloudabi".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_freebsd.rs b/src/librustc_target/spec/i686_unknown_freebsd.rs
index 71f05a1..60f2188 100644
--- a/src/librustc_target/spec/i686_unknown_freebsd.rs
+++ b/src/librustc_target/spec/i686_unknown_freebsd.rs
@@ -4,7 +4,9 @@
     let mut base = super::freebsd_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
+    let pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
+    pre_link_args.push("-m32".to_string());
+    pre_link_args.push("-Wl,-znotext".to_string());
     base.stack_probes = true;
 
     Ok(Target {
@@ -12,7 +14,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "freebsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_haiku.rs b/src/librustc_target/spec/i686_unknown_haiku.rs
index b807e4e..4dc27af 100644
--- a/src/librustc_target/spec/i686_unknown_haiku.rs
+++ b/src/librustc_target/spec/i686_unknown_haiku.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "haiku".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_linux_gnu.rs b/src/librustc_target/spec/i686_unknown_linux_gnu.rs
index 5875cbf..0d578f2 100644
--- a/src/librustc_target/spec/i686_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/i686_unknown_linux_gnu.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/i686_unknown_linux_musl.rs b/src/librustc_target/spec/i686_unknown_linux_musl.rs
index 7329490..699a0ab 100644
--- a/src/librustc_target/spec/i686_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/i686_unknown_linux_musl.rs
@@ -27,7 +27,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/i686_unknown_netbsd.rs b/src/librustc_target/spec/i686_unknown_netbsd.rs
index 01d2b2d..88b1ae7 100644
--- a/src/librustc_target/spec/i686_unknown_netbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_netbsd.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "netbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_openbsd.rs b/src/librustc_target/spec/i686_unknown_openbsd.rs
index d7c323e..829cd1a 100644
--- a/src/librustc_target/spec/i686_unknown_openbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_openbsd.rs
@@ -13,7 +13,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "openbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/i686_unknown_uefi.rs b/src/librustc_target/spec/i686_unknown_uefi.rs
index e4b8b66..345590a 100644
--- a/src/librustc_target/spec/i686_unknown_uefi.rs
+++ b/src/librustc_target/spec/i686_unknown_uefi.rs
@@ -86,7 +86,9 @@
         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(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            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(),
diff --git a/src/librustc_target/spec/i686_uwp_windows_gnu.rs b/src/librustc_target/spec/i686_uwp_windows_gnu.rs
index 1986474..93f396d 100644
--- a/src/librustc_target/spec/i686_uwp_windows_gnu.rs
+++ b/src/librustc_target/spec/i686_uwp_windows_gnu.rs
@@ -18,7 +18,9 @@
         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(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/i686_uwp_windows_msvc.rs b/src/librustc_target/spec/i686_uwp_windows_msvc.rs
index 5e8e8c2..ed2dba5 100644
--- a/src/librustc_target/spec/i686_uwp_windows_msvc.rs
+++ b/src/librustc_target/spec/i686_uwp_windows_msvc.rs
@@ -11,7 +11,9 @@
         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(),
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:32-n8:16:32-a:0:32-S32"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/i686_wrs_vxworks.rs b/src/librustc_target/spec/i686_wrs_vxworks.rs
index c5f9583..f5f66ca 100644
--- a/src/librustc_target/spec/i686_wrs_vxworks.rs
+++ b/src/librustc_target/spec/i686_wrs_vxworks.rs
@@ -12,7 +12,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            f64:32:64-f80:32-n8:16:32-S128"
+            .to_string(),
         arch: "x86".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f08634c..67f45d3 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -472,6 +472,9 @@
     ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
     ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
 
+    ("armv7a-none-eabi", armv7a_none_eabi),
+    ("armv7a-none-eabihf", armv7a_none_eabihf),
+
     ("msp430-none-elf", msp430_none_elf),
 
     ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi),
@@ -805,6 +808,9 @@
 
     /// Whether or not RelaxElfRelocation flag will be passed to the linker
     pub relax_elf_relocations: bool,
+
+    /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
+    pub llvm_args: Vec<String>,
 }
 
 impl Default for TargetOptions {
@@ -893,6 +899,7 @@
             target_mcount: "mcount".to_string(),
             llvm_abiname: "".to_string(),
             relax_elf_relocations: false,
+            llvm_args: vec![],
         }
     }
 }
@@ -1206,6 +1213,7 @@
         key!(target_mcount);
         key!(llvm_abiname);
         key!(relax_elf_relocations, bool);
+        key!(llvm_args, list);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1433,6 +1441,7 @@
         target_option_val!(target_mcount);
         target_option_val!(llvm_abiname);
         target_option_val!(relax_elf_relocations);
+        target_option_val!(llvm_args);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert(
diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs
index 002cee4..e846f42 100644
--- a/src/librustc_target/spec/x86_64_apple_darwin.rs
+++ b/src/librustc_target/spec/x86_64_apple_darwin.rs
@@ -20,7 +20,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: arch.to_string(),
         target_os: "macos".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs
index f8441f9..ca02e2d 100644
--- a/src/librustc_target/spec/x86_64_apple_ios.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios.rs
@@ -8,7 +8,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
index 101d836..5f4f6ad 100644
--- a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
@@ -8,7 +8,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
index 6105eae..3e9552e 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -81,7 +81,8 @@
         target_os: "unknown".into(),
         target_env: "sgx".into(),
         target_vendor: "fortanix".into(),
-        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .into(),
         arch: "x86_64".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         options: opts,
diff --git a/src/librustc_target/spec/x86_64_fuchsia.rs b/src/librustc_target/spec/x86_64_fuchsia.rs
index 5b315bb..37b6d57 100644
--- a/src/librustc_target/spec/x86_64_fuchsia.rs
+++ b/src/librustc_target/spec/x86_64_fuchsia.rs
@@ -11,7 +11,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "fuchsia".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_linux_android.rs b/src/librustc_target/spec/x86_64_linux_android.rs
index c3c6c7b..74097f5 100644
--- a/src/librustc_target/spec/x86_64_linux_android.rs
+++ b/src/librustc_target/spec/x86_64_linux_android.rs
@@ -14,7 +14,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_linux_kernel.rs b/src/librustc_target/spec/x86_64_linux_kernel.rs
index a80b021..89070c9 100644
--- a/src/librustc_target/spec/x86_64_linux_kernel.rs
+++ b/src/librustc_target/spec/x86_64_linux_kernel.rs
@@ -19,7 +19,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-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(),
diff --git a/src/librustc_target/spec/x86_64_pc_windows_gnu.rs b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
index 35e0d55..8f523a3 100644
--- a/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
@@ -11,7 +11,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_pc_windows_msvc.rs b/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
index 073d49b..75ff6b9 100644
--- a/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
@@ -11,7 +11,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
index d71112b..fbade02 100644
--- a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
@@ -18,7 +18,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_sun_solaris.rs b/src/librustc_target/spec/x86_64_sun_solaris.rs
index 3bf3f51..53f4df9 100644
--- a/src/librustc_target/spec/x86_64_sun_solaris.rs
+++ b/src/librustc_target/spec/x86_64_sun_solaris.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "solaris".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_cloudabi.rs b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
index d48120c..dbc5f96 100644
--- a/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
@@ -13,7 +13,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "cloudabi".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_dragonfly.rs b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
index f55ee69..fd1871b 100644
--- a/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "dragonfly".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_freebsd.rs b/src/librustc_target/spec/x86_64_unknown_freebsd.rs
index 1d9c5cc..a124f58 100644
--- a/src/librustc_target/spec/x86_64_unknown_freebsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_freebsd.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "freebsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_haiku.rs b/src/librustc_target/spec/x86_64_unknown_haiku.rs
index 4ab15fa..5123769 100644
--- a/src/librustc_target/spec/x86_64_unknown_haiku.rs
+++ b/src/librustc_target/spec/x86_64_unknown_haiku.rs
@@ -14,7 +14,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "haiku".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_hermit.rs b/src/librustc_target/spec/x86_64_unknown_hermit.rs
index c9123aa..4a526f9 100644
--- a/src/librustc_target/spec/x86_64_unknown_hermit.rs
+++ b/src/librustc_target/spec/x86_64_unknown_hermit.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "hermit".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs b/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs
index 0b1c834..c25cd08 100644
--- a/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs
+++ b/src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs
@@ -14,7 +14,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "hermit".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs b/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
index e5fdb38..cab19f1 100644
--- a/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
+++ b/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
@@ -10,7 +10,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "l4re".to_string(),
         target_env: "uclibc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
index cb279e8..29cbb77 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
index 0b2d7aa..0a37399 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
@@ -16,7 +16,9 @@
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
index 2e1bc83..34c628e 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_netbsd.rs b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
index b0fad314..adf09c8 100644
--- a/src/librustc_target/spec/x86_64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_openbsd.rs b/src/librustc_target/spec/x86_64_unknown_openbsd.rs
index f2abd10..dbd163d 100644
--- a/src/librustc_target/spec/x86_64_unknown_openbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_openbsd.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "openbsd".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/x86_64_unknown_redox.rs b/src/librustc_target/spec/x86_64_unknown_redox.rs
index 8a5af27..3d40baf 100644
--- a/src/librustc_target/spec/x86_64_unknown_redox.rs
+++ b/src/librustc_target/spec/x86_64_unknown_redox.rs
@@ -12,7 +12,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "redox".to_string(),
         target_env: "relibc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_unknown_uefi.rs b/src/librustc_target/spec/x86_64_unknown_uefi.rs
index 443479f..7660b68 100644
--- a/src/librustc_target/spec/x86_64_unknown_uefi.rs
+++ b/src/librustc_target/spec/x86_64_unknown_uefi.rs
@@ -38,7 +38,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         target_os: "uefi".to_string(),
         target_env: "".to_string(),
         target_vendor: "unknown".to_string(),
diff --git a/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs b/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
index da0c324..48366e2 100644
--- a/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
+++ b/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
@@ -11,7 +11,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
index 40dd52c..258df01 100644
--- a/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
+++ b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs
@@ -11,7 +11,8 @@
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/x86_64_wrs_vxworks.rs b/src/librustc_target/spec/x86_64_wrs_vxworks.rs
index 1ab2f3a..f1e27f4 100644
--- a/src/librustc_target/spec/x86_64_wrs_vxworks.rs
+++ b/src/librustc_target/spec/x86_64_wrs_vxworks.rs
@@ -13,7 +13,8 @@
         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(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .to_string(),
         arch: "x86_64".to_string(),
         target_os: "vxworks".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index 4b10b08..0b18352 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -400,7 +400,7 @@
         &mut self,
         value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
     ) -> (Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, UniverseMap) {
-        (value.clone(), UniverseMap)
+        (*value, UniverseMap)
     }
 
     fn invert_goal(
diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs
index 315efe5..7df27e6 100644
--- a/src/librustc_traits/lowering/environment.rs
+++ b/src/librustc_traits/lowering/environment.rs
@@ -195,8 +195,8 @@
         },
 
         Node::Item(item) => match item.kind {
-            ItemKind::Impl(.., Some(..), _, _) => NodeKind::TraitImpl,
-            ItemKind::Impl(.., None, _, _) => NodeKind::InherentImpl,
+            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
+            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
             ItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 47009ac..b77c603 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -1,7 +1,7 @@
 mod environment;
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::definitions::DefPathData;
+use rustc::hir::map::Map;
 use rustc::traits::{
     Clause, Clauses, DomainGoal, FromEnv, GoalKind, PolyDomainGoal, ProgramClause,
     ProgramClauseCategory, WellFormed, WhereClause,
@@ -12,6 +12,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::sym;
 use syntax::ast;
 
@@ -93,7 +94,7 @@
         use rustc::ty::Predicate;
 
         match self {
-            Predicate::Trait(predicate) => predicate.lower(),
+            Predicate::Trait(predicate, _) => predicate.lower(),
             Predicate::RegionOutlives(predicate) => predicate.lower(),
             Predicate::TypeOutlives(predicate) => predicate.lower(),
             Predicate::Projection(predicate) => predicate.lower(),
@@ -600,7 +601,9 @@
 }
 
 impl Visitor<'tcx> for ClauseDumper<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
deleted file mode 100644
index 82045dd..0000000
--- a/src/librustc_tsan/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-build = "build.rs"
-name = "rustc_tsan"
-version = "0.0.0"
-edition = "2018"
-
-[lib]
-name = "rustc_tsan"
-path = "lib.rs"
-test = false
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cmake = "0.1.38"
-
-[dependencies]
-alloc = { path = "../liballoc" }
-core = { path = "../libcore" }
-compiler_builtins = "0.1.0"
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
deleted file mode 100644
index 570642a..0000000
--- a/src/librustc_tsan/build.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use build_helper::sanitizer_lib_boilerplate;
-use std::env;
-
-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();
-
-        let (native, target) = match sanitizer_lib_boilerplate("tsan") {
-            Ok(native) => native,
-            _ => return,
-        };
-
-        Config::new(&native.src_dir)
-            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
-            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
-            .define("COMPILER_RT_BUILD_XRAY", "OFF")
-            .define("LLVM_CONFIG_PATH", llvm_config)
-            .out_dir(&native.out_dir)
-            .build_target(&target)
-            .build();
-        native.fixup_sanitizer_lib_name("tsan");
-    }
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-}
diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs
deleted file mode 100644
index bdbc154..0000000
--- a/src/librustc_tsan/lib.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![sanitizer_runtime]
-#![feature(nll)]
-#![feature(sanitizer_runtime)]
-#![feature(staged_api)]
-#![no_std]
-#![unstable(
-    feature = "sanitizer_runtime_lib",
-    reason = "internal implementation detail of sanitizers",
-    issue = "none"
-)]
diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml
new file mode 100644
index 0000000..fb0d93f
--- /dev/null
+++ b/src/librustc_ty/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_ty"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_ty"
+path = "lib.rs"
+
+[dependencies]
+log = "0.4"
+rustc = { path = "../librustc" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs
new file mode 100644
index 0000000..e5ec987
--- /dev/null
+++ b/src/librustc_ty/lib.rs
@@ -0,0 +1,25 @@
+//! Various checks
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate rustc;
+#[macro_use]
+extern crate log;
+
+use rustc::ty::query::Providers;
+
+mod ty;
+
+pub fn provide(providers: &mut Providers<'_>) {
+    ty::provide(providers);
+}
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
new file mode 100644
index 0000000..8b62403
--- /dev/null
+++ b/src/librustc_ty/ty.rs
@@ -0,0 +1,370 @@
+use rustc::hir::map as hir_map;
+use rustc::session::CrateDisambiguator;
+use rustc::traits::{self};
+use rustc::ty::subst::Subst;
+use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_data_structures::svh::Svh;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_span::symbol::Symbol;
+use rustc_span::Span;
+
+fn sized_constraint_for_ty(tcx: TyCtxt<'tcx>, adtdef: &ty::AdtDef, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
+    use ty::TyKind::*;
+
+    let result = match ty.kind {
+        Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
+        | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
+
+        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
+            // these are never sized - return the target type
+            vec![ty]
+        }
+
+        Tuple(ref tys) => match tys.last() {
+            None => vec![],
+            Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()),
+        },
+
+        Adt(adt, substs) => {
+            // recursive case
+            let adt_tys = adt.sized_constraint(tcx);
+            debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
+            adt_tys
+                .iter()
+                .map(|ty| ty.subst(tcx, substs))
+                .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
+                .collect()
+        }
+
+        Projection(..) | Opaque(..) => {
+            // must calculate explicitly.
+            // FIXME: consider special-casing always-Sized projections
+            vec![ty]
+        }
+
+        UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
+        Param(..) => {
+            // perf hack: if there is a `T: Sized` bound, then
+            // we know that `T` is Sized and do not need to check
+            // it on the impl.
+
+            let sized_trait = match tcx.lang_items().sized_trait() {
+                Some(x) => x,
+                _ => return vec![ty],
+            };
+            let sized_predicate = ty::Binder::dummy(ty::TraitRef {
+                def_id: sized_trait,
+                substs: tcx.mk_substs_trait(ty, &[]),
+            })
+            .without_const()
+            .to_predicate();
+            let predicates = tcx.predicates_of(adtdef.did).predicates;
+            if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
+        }
+
+        Placeholder(..) | Bound(..) | Infer(..) => {
+            bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
+        }
+    };
+    debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
+    result
+}
+
+fn associated_item_from_trait_item_ref(
+    tcx: TyCtxt<'_>,
+    parent_def_id: DefId,
+    parent_vis: &hir::Visibility<'_>,
+    trait_item_ref: &hir::TraitItemRef,
+) -> ty::AssocItem {
+    let def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
+    let (kind, has_self) = match trait_item_ref.kind {
+        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
+        hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
+        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+        hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
+    };
+
+    ty::AssocItem {
+        ident: trait_item_ref.ident,
+        kind,
+        // Visibility of trait items is inherited from their traits.
+        vis: ty::Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, tcx),
+        defaultness: trait_item_ref.defaultness,
+        def_id,
+        container: ty::TraitContainer(parent_def_id),
+        method_has_self_argument: has_self,
+    }
+}
+
+fn associated_item_from_impl_item_ref(
+    tcx: TyCtxt<'_>,
+    parent_def_id: DefId,
+    impl_item_ref: &hir::ImplItemRef<'_>,
+) -> ty::AssocItem {
+    let def_id = tcx.hir().local_def_id(impl_item_ref.id.hir_id);
+    let (kind, has_self) = match impl_item_ref.kind {
+        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
+        hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
+        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+        hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
+    };
+
+    ty::AssocItem {
+        ident: impl_item_ref.ident,
+        kind,
+        // Visibility of trait impl items doesn't matter.
+        vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, tcx),
+        defaultness: impl_item_ref.defaultness,
+        def_id,
+        container: ty::ImplContainer(parent_def_id),
+        method_has_self_argument: has_self,
+    }
+}
+
+fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
+    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let parent_id = tcx.hir().get_parent_item(id);
+    let parent_def_id = tcx.hir().local_def_id(parent_id);
+    let parent_item = tcx.hir().expect_item(parent_id);
+    match parent_item.kind {
+        hir::ItemKind::Impl { ref items, .. } => {
+            if let Some(impl_item_ref) = items.iter().find(|i| i.id.hir_id == id) {
+                let assoc_item =
+                    associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
+                let assoc_item = associated_item_from_trait_item_ref(
+                    tcx,
+                    parent_def_id,
+                    &parent_item.vis,
+                    trait_item_ref,
+                );
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        _ => {}
+    }
+
+    span_bug!(
+        parent_item.span,
+        "unexpected parent of trait or impl item or item not found: {:?}",
+        parent_item.kind
+    )
+}
+
+/// Calculates the `Sized` constraint.
+///
+/// In fact, there are only a few options for the types in the constraint:
+///     - an obviously-unsized type
+///     - a type parameter or projection whose Sizedness can't be known
+///     - a tuple of type parameters or projections, if there are multiple
+///       such.
+///     - a Error, if a type contained itself. The representability
+///       check should catch this case.
+fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
+    let def = tcx.adt_def(def_id);
+
+    let result = tcx.mk_type_list(
+        def.variants
+            .iter()
+            .flat_map(|v| v.fields.last())
+            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
+    );
+
+    debug!("adt_sized_constraint: {:?} => {:?}", def, result);
+
+    ty::AdtSizedConstraint(result)
+}
+
+fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
+    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let item = tcx.hir().expect_item(id);
+    match item.kind {
+        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
+            trait_item_refs
+                .iter()
+                .map(|trait_item_ref| trait_item_ref.id)
+                .map(|id| tcx.hir().local_def_id(id.hir_id)),
+        ),
+        hir::ItemKind::Impl { ref items, .. } => tcx.arena.alloc_from_iter(
+            items
+                .iter()
+                .map(|impl_item_ref| impl_item_ref.id)
+                .map(|id| tcx.hir().local_def_id(id.hir_id)),
+        ),
+        hir::ItemKind::TraitAlias(..) => &[],
+        _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
+    }
+}
+
+fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
+    tcx.hir().span_if_local(def_id).unwrap()
+}
+
+/// If the given `DefId` describes an item belonging to a trait,
+/// returns the `DefId` of the trait that the trait item belongs to;
+/// otherwise, returns `None`.
+fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
+    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
+        ty::TraitContainer(def_id) => Some(def_id),
+        ty::ImplContainer(_) => None,
+    })
+}
+
+/// See `ParamEnv` struct definition for details.
+fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
+    // The param_env of an impl Trait type is its defining function's param_env
+    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
+        return param_env(tcx, parent);
+    }
+    // Compute the bounds on Self and the type parameters.
+
+    let ty::InstantiatedPredicates { predicates } =
+        tcx.predicates_of(def_id).instantiate_identity(tcx);
+
+    // Finally, we have to normalize the bounds in the environment, in
+    // case they contain any associated type projections. This process
+    // can yield errors if the put in illegal associated types, like
+    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+    // report these errors right here; this doesn't actually feel
+    // right to me, because constructing the environment feels like a
+    // kind of a "idempotent" action, but I'm not sure where would be
+    // a better place. In practice, we construct environments for
+    // every fn once during type checking, and we'll abort if there
+    // are any errors at that point, so after type checking you can be
+    // sure that this will succeed without errors anyway.
+
+    let unnormalized_env = ty::ParamEnv::new(
+        tcx.intern_predicates(&predicates),
+        traits::Reveal::UserFacing,
+        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
+    );
+
+    let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
+        tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
+    });
+    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
+    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
+}
+
+fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.sess.local_crate_disambiguator()
+}
+
+fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.crate_name.clone()
+}
+
+fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.hir().crate_hash
+}
+
+fn instance_def_size_estimate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance_def: ty::InstanceDef<'tcx>,
+) -> usize {
+    use ty::InstanceDef;
+
+    match instance_def {
+        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
+            let mir = tcx.instance_mir(instance_def);
+            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
+        }
+        // Estimate the size of other compiler-generated shims to be 1.
+        _ => 1,
+    }
+}
+
+/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
+///
+/// See [`ImplOverlapKind::Issue33140`] for more details.
+fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
+    debug!("issue33140_self_ty({:?})", def_id);
+
+    let trait_ref = tcx
+        .impl_trait_ref(def_id)
+        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
+
+    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
+
+    let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
+        && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
+
+    // Check whether these impls would be ok for a marker trait.
+    if !is_marker_like {
+        debug!("issue33140_self_ty - not marker-like!");
+        return None;
+    }
+
+    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
+    if trait_ref.substs.len() != 1 {
+        debug!("issue33140_self_ty - impl has substs!");
+        return None;
+    }
+
+    let predicates = tcx.predicates_of(def_id);
+    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
+        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
+        return None;
+    }
+
+    let self_ty = trait_ref.self_ty();
+    let self_ty_matches = match self_ty.kind {
+        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
+        _ => false,
+    };
+
+    if self_ty_matches {
+        debug!("issue33140_self_ty - MATCHES!");
+        Some(self_ty)
+    } else {
+        debug!("issue33140_self_ty - non-matching self type");
+        None
+    }
+}
+
+/// Check if a function is async.
+fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
+    let hir_id = tcx
+        .hir()
+        .as_local_hir_id(def_id)
+        .unwrap_or_else(|| bug!("asyncness: expected local `DefId`, got `{:?}`", def_id));
+
+    let node = tcx.hir().get(hir_id);
+
+    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
+        bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
+    });
+
+    fn_like.asyncness()
+}
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers {
+        asyncness,
+        associated_item,
+        associated_item_def_ids,
+        adt_sized_constraint,
+        def_span,
+        param_env,
+        trait_of_item,
+        crate_disambiguator,
+        original_crate_name,
+        crate_hash,
+        instance_def_size_estimate,
+        issue33140_self_ty,
+        ..*providers
+    };
+}
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index a489d0c..4b27d86 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -15,11 +15,10 @@
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_index = { path = "../librustc_index" }
-rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5acaede..89eeed8 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1,7 +1,10 @@
+// ignore-tidy-filelength FIXME(#67418) Split up this file.
 //! Conversion from AST representation of types to the `ty.rs` representation.
 //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
 //! instance of `AstConv`.
 
+// ignore-tidy-filelength
+
 use crate::collect::PlaceholderHirTyCollector;
 use crate::lint;
 use crate::middle::lang_items::SizedTraitLangItem;
@@ -9,36 +12,35 @@
 use crate::namespace::Namespace;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
-use errors::{Applicability, DiagnosticId};
-use rustc::hir::intravisit::Visitor;
 use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
+use rustc::session::parse::feature_err;
 use rustc::traits;
 use rustc::traits::astconv_object_safety_violations;
 use rustc::traits::error_reporting::report_object_safety_error;
 use rustc::traits::wf::object_region_bounds;
 use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
-use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::print;
 use rustc_hir::{ExprKind, GenericArg, GenericArgs};
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use smallvec::SmallVec;
-use syntax::ast;
-use syntax::errors::pluralize;
-use syntax::feature_gate::feature_err;
+use syntax::ast::{self, Constness};
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use std::collections::BTreeSet;
 use std::iter;
 use std::slice;
 
-use rustc_error_codes::*;
+use rustc::mir::interpret::LitToConstInput;
 
 #[derive(Debug)]
 pub struct PathSeg(pub DefId, pub usize);
@@ -48,6 +50,8 @@
 
     fn item_def_id(&self) -> Option<DefId>;
 
+    fn default_constness_for_trait_bounds(&self) -> Constness;
+
     /// Returns predicates in scope of the form `X: Foo`, where `X` is
     /// a type parameter `X` with the given id `def_id`. This is a
     /// subset of the full set of predicates.
@@ -918,6 +922,7 @@
         &self,
         trait_ref: &hir::TraitRef<'_>,
         span: Span,
+        constness: Constness,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
@@ -946,7 +951,7 @@
         );
         let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
 
-        bounds.trait_bounds.push((poly_trait_ref, span));
+        bounds.trait_bounds.push((poly_trait_ref, span, constness));
 
         let mut dup_bindings = FxHashMap::default();
         for binding in &assoc_bindings {
@@ -992,12 +997,14 @@
     pub fn instantiate_poly_trait_ref(
         &self,
         poly_trait_ref: &hir::PolyTraitRef<'_>,
+        constness: Constness,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
     ) -> Option<Vec<Span>> {
         self.instantiate_poly_trait_ref_inner(
             &poly_trait_ref.trait_ref,
             poly_trait_ref.span,
+            constness,
             self_ty,
             bounds,
             false,
@@ -1119,13 +1126,14 @@
                 if unbound.is_none() {
                     unbound = Some(&ptr.trait_ref);
                 } else {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0203,
                         "type parameter has more than one relaxed default \
                         bound, only one is supported"
-                    );
+                    )
+                    .emit();
                 }
             }
         }
@@ -1179,18 +1187,22 @@
         let mut trait_bounds = Vec::new();
         let mut region_bounds = Vec::new();
 
+        let constness = self.default_constness_for_trait_bounds();
         for ast_bound in ast_bounds {
             match *ast_bound {
                 hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
-                    trait_bounds.push(b)
+                    trait_bounds.push((b, constness))
+                }
+                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
+                    trait_bounds.push((b, Constness::NotConst))
                 }
                 hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
                 hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
             }
         }
 
-        for bound in trait_bounds {
-            let _ = self.instantiate_poly_trait_ref(bound, param_ty, bounds);
+        for (bound, constness) in trait_bounds {
+            let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds);
         }
 
         bounds.region_bounds.extend(
@@ -1224,7 +1236,7 @@
         let mut bounds = Bounds::default();
 
         self.add_bounds(param_ty, ast_bounds, &mut bounds);
-        bounds.trait_bounds.sort_by_key(|(t, _)| t.def_id());
+        bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
 
         bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
             if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
@@ -1318,10 +1330,10 @@
                 // those that do.
                 self.one_bound_for_assoc_type(
                     || traits::supertraits(tcx, trait_ref),
-                    &trait_ref.print_only_trait_path().to_string(),
+                    || trait_ref.print_only_trait_path().to_string(),
                     binding.item_name,
                     path_span,
-                    match binding.kind {
+                    || match binding.kind {
                         ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
                         _ => None,
                     },
@@ -1415,15 +1427,21 @@
         let mut potential_assoc_types = Vec::new();
         let dummy_self = self.tcx().types.trait_object_dummy_self;
         for trait_bound in trait_bounds.iter().rev() {
-            let cur_potential_assoc_types =
-                self.instantiate_poly_trait_ref(trait_bound, dummy_self, &mut bounds);
+            let cur_potential_assoc_types = self.instantiate_poly_trait_ref(
+                trait_bound,
+                Constness::NotConst,
+                dummy_self,
+                &mut bounds,
+            );
             potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten());
         }
 
         // Expand trait aliases recursively and check that only one regular (non-auto) trait
         // is used and no 'maybe' bounds are used.
-        let expanded_traits =
-            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned());
+        let expanded_traits = traits::expand_trait_aliases(
+            tcx,
+            bounds.trait_bounds.iter().map(|&(a, b, _)| (a.clone(), b)),
+        );
         let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
             expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
         if regular_traits.len() > 1 {
@@ -1445,7 +1463,13 @@
         }
 
         if regular_traits.is_empty() && auto_traits.is_empty() {
-            span_err!(tcx.sess, span, E0224, "at least one trait is required for an object type");
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0224,
+                "at least one trait is required for an object type"
+            )
+            .emit();
             return tcx.types.err;
         }
 
@@ -1473,16 +1497,18 @@
         let regular_traits_refs_spans = bounds
             .trait_bounds
             .into_iter()
-            .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
+            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
 
-        for (base_trait_ref, span) in regular_traits_refs_spans {
+        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
+            assert_eq!(constness, ast::Constness::NotConst);
+
             for trait_ref in traits::elaborate_trait_ref(tcx, base_trait_ref) {
                 debug!(
                     "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
                     trait_ref
                 );
                 match trait_ref {
-                    ty::Predicate::Trait(pred) => {
+                    ty::Predicate::Trait(pred, _) => {
                         associated_types.entry(span).or_default().extend(
                             tcx.associated_items(pred.def_id())
                                 .filter(|item| item.kind == ty::AssocKind::Type)
@@ -1601,13 +1627,14 @@
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(None, span).unwrap_or_else(|| {
-                        span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0228,
                             "the lifetime bound for this object type cannot be deduced \
                              from context; please supply an explicit bound"
-                        );
+                        )
+                        .emit();
                         tcx.lifetimes.re_static
                     })
                 }
@@ -1871,10 +1898,10 @@
                     predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
                 )
             },
-            &param_name.as_str(),
+            || param_name.to_string(),
             assoc_name,
             span,
-            None,
+            || None,
         )
     }
 
@@ -1883,10 +1910,10 @@
     fn one_bound_for_assoc_type<I>(
         &self,
         all_candidates: impl Fn() -> I,
-        ty_param_name: &str,
+        ty_param_name: impl Fn() -> String,
         assoc_name: ast::Ident,
         span: Span,
-        is_equality: Option<String>,
+        is_equality: impl Fn() -> Option<String>,
     ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
     where
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@@ -1899,7 +1926,7 @@
             None => {
                 self.complain_about_assoc_type_not_found(
                     all_candidates,
-                    ty_param_name,
+                    &ty_param_name(),
                     assoc_name,
                     span,
                 );
@@ -1912,6 +1939,7 @@
         if let Some(bound2) = matching_candidates.next() {
             debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
 
+            let is_equality = is_equality();
             let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
             let mut err = if is_equality.is_some() {
                 // More specific Error Index entry.
@@ -1921,7 +1949,7 @@
                     E0222,
                     "ambiguous associated type `{}` in bounds of `{}`",
                     assoc_name,
-                    ty_param_name
+                    ty_param_name()
                 )
             } else {
                 struct_span_err!(
@@ -1930,7 +1958,7 @@
                     E0221,
                     "ambiguous associated type `{}` in bounds of `{}`",
                     assoc_name,
-                    ty_param_name
+                    ty_param_name()
                 )
             };
             err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
@@ -1968,7 +1996,7 @@
                             "use fully qualified syntax to disambiguate",
                             format!(
                                 "<{} as {}>::{}",
-                                ty_param_name,
+                                ty_param_name(),
                                 bound.print_only_trait_path(),
                                 assoc_name,
                             ),
@@ -1978,7 +2006,7 @@
                 } else {
                     err.note(&format!(
                         "associated type `{}` could derive from `{}`",
-                        ty_param_name,
+                        ty_param_name(),
                         bound.print_only_trait_path(),
                     ));
                 }
@@ -1987,7 +2015,7 @@
                 err.help(&format!(
                     "consider introducing a new type parameter `T` and adding `where` constraints:\
                      \n    where\n        T: {},\n{}",
-                    ty_param_name,
+                    ty_param_name(),
                     where_bounds.join(",\n"),
                 ));
             }
@@ -2101,10 +2129,10 @@
 
                 self.one_bound_for_assoc_type(
                     || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
-                    "Self",
+                    || "Self".to_string(),
                     assoc_ident,
                     span,
-                    None,
+                    || None,
                 )?
             }
             (&ty::Param(_), Res::SelfTy(Some(param_did), None))
@@ -2117,9 +2145,13 @@
                     let msg = format!("expected type, found variant `{}`", assoc_ident);
                     tcx.sess.span_err(span, &msg);
                 } else if qself_ty.is_enum() {
-                    let mut err = tcx.sess.struct_span_err(
+                    let mut err = struct_span_err!(
+                        tcx.sess,
                         assoc_ident.span,
-                        &format!("no variant `{}` in enum `{}`", assoc_ident, qself_ty),
+                        E0599,
+                        "no variant named `{}` found for enum `{}`",
+                        assoc_ident,
+                        qself_ty,
                     );
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
@@ -2688,13 +2720,28 @@
         let tcx = self.tcx();
         let def_id = tcx.hir().local_def_id(ast_const.hir_id);
 
-        let mut const_ = ty::Const {
-            val: ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id)),
-            ty,
+        let expr = &tcx.hir().body(ast_const.body).value;
+
+        let lit_input = match expr.kind {
+            hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+            hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind {
+                hir::ExprKind::Lit(ref lit) => {
+                    Some(LitToConstInput { lit: &lit.node, ty, neg: true })
+                }
+                _ => None,
+            },
+            _ => None,
         };
 
-        let expr = &tcx.hir().body(ast_const.body).value;
-        if let Some(def_id) = self.const_param_def_id(expr) {
+        if let Some(lit_input) = lit_input {
+            // If an error occurred, ignore that it's a literal and leave reporting the error up to
+            // mir.
+            if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
+                return c;
+            }
+        }
+
+        let kind = if let Some(def_id) = self.const_param_def_id(expr) {
             // Find the name and index of the const parameter by indexing the generics of the
             // parent item and construct a `ParamConst`.
             let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -2703,10 +2750,11 @@
             let generics = tcx.generics_of(item_def_id);
             let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)];
             let name = tcx.hir().name(hir_id);
-            const_.val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
-        }
-
-        tcx.mk_const(const_)
+            ty::ConstKind::Param(ty::ParamConst::new(index, name))
+        } else {
+            ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id), None)
+        };
+        tcx.mk_const(ty::Const { val: kind, ty })
     }
 
     pub fn impl_trait_ty_to_ty(
@@ -2795,7 +2843,7 @@
             // allowed. `allow_ty_infer` gates this behavior.
             crate::collect::placeholder_type_error(
                 tcx,
-                ident_span.unwrap_or(DUMMY_SP),
+                ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP),
                 generic_params,
                 visitor.0,
                 ident_span.is_some(),
@@ -2880,12 +2928,13 @@
         // error.
         let r = derived_region_bounds[0];
         if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            span_err!(
+            struct_span_err!(
                 tcx.sess,
                 span,
                 E0227,
                 "ambiguous lifetime bound, explicit lifetime bound required"
-            );
+            )
+            .emit();
         }
         return Some(r);
     }
@@ -2918,7 +2967,7 @@
 
     /// A list of trait bounds. So if you had `T: Debug` this would be
     /// `T: Debug`. Note that the self-type is explicit here.
-    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span)>,
+    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
 
     /// A list of projection equality bounds. So if you had `T:
     /// Iterator<Item = u32>` this would include `<T as
@@ -2949,7 +2998,7 @@
                     def_id: sized,
                     substs: tcx.mk_substs_trait(param_ty, &[]),
                 });
-                (trait_ref.to_predicate(), span)
+                (trait_ref.without_const().to_predicate(), span)
             })
         });
 
@@ -2966,11 +3015,10 @@
                         let outlives = ty::OutlivesPredicate(param_ty, region_bound);
                         (ty::Binder::bind(outlives).to_predicate(), span)
                     })
-                    .chain(
-                        self.trait_bounds
-                            .iter()
-                            .map(|&(bound_trait_ref, span)| (bound_trait_ref.to_predicate(), span)),
-                    )
+                    .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
+                        let predicate = bound_trait_ref.with_constness(constness).to_predicate();
+                        (predicate, span)
+                    }))
                     .chain(
                         self.projection_bounds
                             .iter()
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index bd84547..686cdfb 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -50,30 +50,13 @@
 
         self.warn_arms_when_scrutinee_diverges(arms, match_src);
 
-        // Otherwise, we have to union together the types that the
-        // arms produce and so forth.
-        let scrut_diverges = self.diverges.get();
-        self.diverges.set(Diverges::Maybe);
+        // Otherwise, we have to union together the types that the arms produce and so forth.
+        let scrut_diverges = self.diverges.replace(Diverges::Maybe);
 
-        // rust-lang/rust#55810: Typecheck patterns first (via eager
-        // collection into `Vec`), so we get types for all bindings.
-        let all_arm_pats_diverge: Vec<_> = arms
-            .iter()
-            .map(|arm| {
-                let mut all_pats_diverge = Diverges::WarnedAlways;
-                self.diverges.set(Diverges::Maybe);
-                self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true);
-                all_pats_diverge &= self.diverges.get();
-
-                // As discussed with @eddyb, this is for disabling unreachable_code
-                // warnings on patterns (they're now subsumed by unreachable_patterns
-                // warnings).
-                match all_pats_diverge {
-                    Diverges::Maybe => Diverges::Maybe,
-                    Diverges::Always { .. } | Diverges::WarnedAlways => Diverges::WarnedAlways,
-                }
-            })
-            .collect();
+        // #55810: Type check patterns first so we get types for all bindings.
+        for arm in arms {
+            self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true);
+        }
 
         // Now typecheck the blocks.
         //
@@ -104,11 +87,11 @@
             CoerceMany::with_coercion_sites(coerce_first, arms)
         };
 
-        let mut other_arms = vec![]; // used only for diagnostics
+        let mut other_arms = vec![]; // Used only for diagnostics.
         let mut prior_arm_ty = None;
-        for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
+        for (i, arm) in arms.iter().enumerate() {
             if let Some(g) = &arm.guard {
-                self.diverges.set(pats_diverge);
+                self.diverges.set(Diverges::Maybe);
                 match g {
                     hir::Guard::If(e) => {
                         self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {})
@@ -116,7 +99,7 @@
                 };
             }
 
-            self.diverges.set(pats_diverge);
+            self.diverges.set(Diverges::Maybe);
             let arm_ty = if source_if
                 && if_no_else
                 && i != 0
@@ -200,16 +183,14 @@
         arms: &'tcx [hir::Arm<'tcx>],
         source: hir::MatchSource,
     ) {
-        if self.diverges.get().is_always() {
-            use hir::MatchSource::*;
-            let msg = match source {
-                IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression",
-                WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression",
-                _ => "arm",
-            };
-            for arm in arms {
-                self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
-            }
+        use hir::MatchSource::*;
+        let msg = match source {
+            IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression",
+            WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression",
+            _ => "arm",
+        };
+        for arm in arms {
+            self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
         }
     }
 
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 3b4f408b..e4dec97 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -5,15 +5,14 @@
 use rustc::session::DiagnosticMessageId;
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
-use rustc::ty::{self, TraitRef, Ty, TyCtxt};
+use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
 use rustc::ty::{ToPredicate, TypeFoldable};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 
 use rustc_span::Span;
 use syntax::ast::Ident;
 
-use rustc_error_codes::*;
-
 use std::iter;
 
 #[derive(Copy, Clone, Debug)]
@@ -123,8 +122,11 @@
 
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
 
-        let obligation =
-            traits::Obligation::new(cause.clone(), self.param_env, trait_ref.to_predicate());
+        let obligation = traits::Obligation::new(
+            cause.clone(),
+            self.param_env,
+            trait_ref.without_const().to_predicate(),
+        );
         if !self.infcx.predicate_may_hold(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
             return None;
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 23db0fc..b33cc52 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -1,23 +1,21 @@
 use super::autoderef::Autoderef;
 use super::method::MethodCallee;
 use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
+use crate::type_error_struct;
 
-use errors::{Applicability, DiagnosticBuilder};
-use hir::def::Res;
-use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::{infer, traits};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use syntax::ast::Ident;
 
-use rustc_hir as hir;
-
-use rustc_error_codes::*;
-
 /// Checks that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called).
@@ -241,7 +239,7 @@
         ) = (parent_node, callee_node)
         {
             let start = sp.shrink_to_lo();
-            let end = self.tcx.sess.source_map().next_point(callee_span);
+            let end = callee_span.shrink_to_hi();
             err.multipart_suggestion(
                 "if you meant to create this closure and immediately call it, surround the \
                 closure with parenthesis",
@@ -318,9 +316,8 @@
                             let call_is_multiline =
                                 self.tcx.sess.source_map().is_multiline(call_expr.span);
                             if call_is_multiline {
-                                let span = self.tcx.sess.source_map().next_point(callee.span);
                                 err.span_suggestion(
-                                    span,
+                                    callee.span.shrink_to_hi(),
                                     "try adding a semicolon",
                                     ";".to_owned(),
                                     Applicability::MaybeIncorrect,
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 0be21ad..d254a84 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -32,8 +32,8 @@
 
 use crate::hir::def_id::DefId;
 use crate::lint;
+use crate::type_error_struct;
 use crate::util::common::ErrorReported;
-use errors::{Applicability, DiagnosticBuilder};
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::traits;
@@ -44,12 +44,11 @@
 use rustc::ty::error::TypeError;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
 pub struct CastCheck<'tcx> {
@@ -380,7 +379,7 @@
                     if unknown_cast_to { "to" } else { "from" }
                 );
                 err.note(
-                    "The type information given here is insufficient to check whether \
+                    "the type information given here is insufficient to check whether \
                           the pointer cast is valid",
                 );
                 if unknown_cast_to {
@@ -425,17 +424,16 @@
                             );
                         }
                         Err(_) => {
-                            span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr)
+                            let msg = &format!("did you mean `&{}{}`?", mtstr, tstr);
+                            err.span_help(self.cast_span, msg);
                         }
                     }
                 } else {
-                    span_help!(
-                        err,
-                        self.span,
+                    let msg = &format!(
                         "consider using an implicit coercion to `&{}{}` instead",
-                        mtstr,
-                        tstr
+                        mtstr, tstr
                     );
+                    err.span_help(self.span, msg);
                 }
             }
             ty::Adt(def, ..) if def.is_box() => {
@@ -448,11 +446,13 @@
                             Applicability::MachineApplicable,
                         );
                     }
-                    Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
+                    Err(_) => {
+                        err.span_help(self.cast_span, &format!("did you mean `Box<{}>`?", tstr));
+                    }
                 }
             }
             _ => {
-                span_help!(err, self.expr.span, "consider using a box or reference as appropriate");
+                err.span_help(self.expr.span, "consider using a box or reference as appropriate");
             }
         }
         err.emit();
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 6bb7f49..084e6c8 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -175,7 +175,7 @@
             }
             ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
             ty::FnPtr(sig) => {
-                let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder().clone() };
+                let expected_sig = ExpectedSig { cause_span: None, sig: *sig.skip_binder() };
                 (Some(expected_sig), Some(ty::ClosureKind::Fn))
             }
             _ => (None, None),
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 36ad6ea..54b32c3 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -50,10 +50,12 @@
 //! sort of a minor point so I've opted to leave it for later -- after all,
 //! we may want to adjust precisely when coercions occur.
 
+use crate::astconv::AstConv;
 use crate::check::{FnCtxt, Needs};
-use errors::DiagnosticBuilder;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{Coercion, InferOk, InferResult};
+use rustc::session::parse::feature_err;
+use rustc::traits::object_safety_violations;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -63,16 +65,14 @@
 use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut};
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_span;
 use rustc_span::symbol::sym;
+use rustc_span::{self, Span};
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
-use syntax::feature_gate;
-
-use rustc_error_codes::*;
 
 struct Coerce<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -564,7 +564,7 @@
             let obligation = queue.remove(0);
             debug!("coerce_unsized resolve step: {:?}", obligation);
             let trait_ref = match obligation.predicate {
-                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
+                ty::Predicate::Trait(ref tr, _) if traits.contains(&tr.def_id()) => {
                     if unsize_did == tr.def_id() {
                         let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind;
                         if let ty::Tuple(..) = sty {
@@ -627,7 +627,7 @@
         }
 
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
-            feature_gate::feature_err(
+            feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::unsized_tuple_coercion,
                 self.cause.span,
@@ -1223,6 +1223,7 @@
                 };
 
                 let mut err;
+                let mut unsized_return = false;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
                         err = struct_span_err!(
@@ -1244,6 +1245,9 @@
                             parent_id,
                             expression.map(|expr| (expr, blk_id)),
                         );
+                        if !fcx.tcx.features().unsized_locals {
+                            unsized_return = self.is_return_ty_unsized(fcx, blk_id);
+                        }
                     }
                     ObligationCauseCode::ReturnValue(id) => {
                         err = self.report_return_mismatched_types(
@@ -1255,6 +1259,10 @@
                             id,
                             None,
                         );
+                        if !fcx.tcx.features().unsized_locals {
+                            let id = fcx.tcx.hir().get_parent_node(id);
+                            unsized_return = self.is_return_ty_unsized(fcx, id);
+                        }
                     }
                     _ => {
                         err = fcx.report_mismatched_types(cause, expected, found, coercion_error);
@@ -1283,7 +1291,7 @@
                     .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
                     .is_some();
 
-                err.emit_unless(assign_to_bool);
+                err.emit_unless(assign_to_bool || unsized_return);
 
                 self.final_ty = Some(fcx.tcx.types.err);
             }
@@ -1303,7 +1311,7 @@
         let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
 
         let mut pointing_at_return_type = false;
-        let mut return_sp = None;
+        let mut fn_output = None;
 
         // Verify that this is a tail expression of a function, otherwise the
         // label pointing out the cause for the type coercion will be wrong
@@ -1340,19 +1348,98 @@
                 );
             }
             if !pointing_at_return_type {
-                return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
+                fn_output = Some(&fn_decl.output); // `impl Trait` return type
             }
         }
-        if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
-            err.span_label(return_sp, "expected because this return type...");
-            err.span_label( *sp, format!(
-                "...is found to be `{}` here",
-                fcx.resolve_vars_with_obligations(expected),
-            ));
+        if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) {
+            self.add_impl_trait_explanation(&mut err, fcx, expected, *sp, fn_output);
         }
         err
     }
 
+    fn add_impl_trait_explanation<'a>(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        fcx: &FnCtxt<'a, 'tcx>,
+        expected: Ty<'tcx>,
+        sp: Span,
+        fn_output: &hir::FunctionRetTy<'_>,
+    ) {
+        let return_sp = fn_output.span();
+        err.span_label(return_sp, "expected because this return type...");
+        err.span_label(
+            sp,
+            format!("...is found to be `{}` here", fcx.resolve_vars_with_obligations(expected)),
+        );
+        let impl_trait_msg = "for information on `impl Trait`, see \
+                <https://doc.rust-lang.org/book/ch10-02-traits.html\
+                #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+                <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+                #using-trait-objects-that-allow-for-values-of-different-types>";
+        err.note("to return `impl Trait`, all returned values must be of the same type");
+        err.note(impl_trait_msg);
+        let snippet = fcx
+            .tcx
+            .sess
+            .source_map()
+            .span_to_snippet(return_sp)
+            .unwrap_or_else(|_| "dyn Trait".to_string());
+        let mut snippet_iter = snippet.split_whitespace();
+        let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
+        // Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
+        let mut is_object_safe = false;
+        if let hir::FunctionRetTy::Return(ty) = fn_output {
+            // Get the return type.
+            if let hir::TyKind::Def(..) = ty.kind {
+                let ty = AstConv::ast_ty_to_ty(fcx, ty);
+                // Get the `impl Trait`'s `DefId`.
+                if let ty::Opaque(def_id, _) = ty.kind {
+                    let hir_id = fcx.tcx.hir().as_local_hir_id(def_id).unwrap();
+                    // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
+                    // get the `Trait`'s `DefId`.
+                    if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
+                        fcx.tcx.hir().expect_item(hir_id).kind
+                    {
+                        // Are of this `impl Trait`'s traits object safe?
+                        is_object_safe = bounds.iter().all(|bound| {
+                            bound.trait_def_id().map_or(false, |def_id| {
+                                object_safety_violations(fcx.tcx, def_id).is_empty()
+                            })
+                        })
+                    }
+                }
+            }
+        };
+        if has_impl {
+            if is_object_safe {
+                err.help(&format!(
+                    "you can instead return a boxed trait object using `Box<dyn {}>`",
+                    &snippet[5..]
+                ));
+            } else {
+                err.help(&format!(
+                    "if the trait `{}` were object safe, you could return a boxed trait object",
+                    &snippet[5..]
+                ));
+            }
+            err.note(trait_obj_msg);
+        }
+        err.help("alternatively, create a new `enum` with a variant for each returned type");
+    }
+
+    fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
+        if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
+            if let hir::FunctionRetTy::Return(ty) = fn_decl.output {
+                let ty = AstConv::ast_ty_to_ty(fcx, ty);
+                if let ty::Dynamic(..) = ty.kind {
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
     pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
         if let Some(final_ty) = self.final_ty {
             final_ty
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 13e37c1..414f80d 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1,5 +1,4 @@
-use errors::{Applicability, DiagnosticId};
-use rustc::hir::intravisit;
+use rustc::hir::map::Map;
 use rustc::infer::{self, InferOk};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
@@ -7,16 +6,15 @@
 use rustc::ty::util::ExplicitSelf;
 use rustc::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc::util::common::ErrorReported;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_span::Span;
-use syntax::errors::pluralize;
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
 
-use rustc_error_codes::*;
-
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
 ///
@@ -891,9 +889,10 @@
                                     }
                                 }
                             }
-                            fn nested_visit_map<'this>(
-                                &'this mut self,
-                            ) -> intravisit::NestedVisitorMap<'this, 'v>
+                            type Map = Map<'v>;
+                            fn nested_visit_map(
+                                &mut self,
+                            ) -> intravisit::NestedVisitorMap<'_, Self::Map>
                             {
                                 intravisit::NestedVisitorMap::None
                             }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 1be65b5..e0f9fcc 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -2,9 +2,9 @@
 use rustc::infer::InferOk;
 use rustc::traits::{self, ObligationCause};
 
-use errors::{Applicability, DiagnosticBuilder};
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::{self, AssocItem, Ty};
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, print, Node};
 use rustc_span::symbol::sym;
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 004fce7..32773e2 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -1,5 +1,4 @@
 use crate::check::regionck::RegionCtxt;
-
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::util::common::ErrorReported;
@@ -11,11 +10,10 @@
 use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, Predicate, Ty, TyCtxt};
+use rustc_errors::struct_span_err;
 
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 /// This function confirms that the `Drop` implementation identified by
 /// `drop_impl_did` is not any more specialized than the type it is
 /// attached to (Issue #8142).
@@ -234,7 +232,7 @@
         let predicate_matches_closure = |p: &'_ Predicate<'tcx>| {
             let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
             match (predicate, p) {
-                (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(),
+                (Predicate::Trait(a, _), Predicate::Trait(b, _)) => relator.relate(a, b).is_ok(),
                 (Predicate::Projection(a), Predicate::Projection(b)) => {
                     relator.relate(a, b).is_ok()
                 }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index c12d840..b4c2b85 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -14,9 +14,9 @@
 use crate::check::FnCtxt;
 use crate::check::Needs;
 use crate::check::TupleArgumentsFlag::DontTupleArguments;
+use crate::type_error_struct;
 use crate::util::common::ErrorReported;
 
-use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::middle::lang_items;
@@ -27,6 +27,7 @@
 use rustc::ty::TypeFoldable;
 use rustc::ty::{AdtKind, Visibility};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -37,8 +38,6 @@
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
-
 use std::fmt::Display;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -166,10 +165,8 @@
         }
 
         // Hide the outer diverging and has_errors flags.
-        let old_diverges = self.diverges.get();
-        let old_has_errors = self.has_errors.get();
-        self.diverges.set(Diverges::Maybe);
-        self.has_errors.set(false);
+        let old_diverges = self.diverges.replace(Diverges::Maybe);
+        let old_has_errors = self.has_errors.replace(false);
 
         let ty = self.check_expr_kind(expr, expected, needs);
 
@@ -1108,13 +1105,14 @@
         // Prohibit struct expressions when non-exhaustive flag is set.
         let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
         if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
-            span_err!(
+            struct_span_err!(
                 self.tcx.sess,
                 expr.span,
                 E0639,
                 "cannot create non-exhaustive {} using struct expression",
                 adt.variant_descr()
-            );
+            )
+            .emit();
         }
 
         let error_happened = self.check_expr_struct_fields(
@@ -1152,12 +1150,13 @@
                             .insert(expr.hir_id, fru_field_types);
                     }
                     _ => {
-                        span_err!(
+                        struct_span_err!(
                             self.tcx.sess,
                             base_expr.span,
                             E0436,
                             "functional record update syntax requires a struct"
-                        );
+                        )
+                        .emit();
                     }
                 }
             }
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index f004d04..75cc2c1 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -4,13 +4,14 @@
 //! types computed here.
 
 use super::FnCtxt;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::middle::region::{self, YieldData};
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, ExprKind, Pat, PatKind};
 use rustc_span::Span;
 
@@ -96,6 +97,7 @@
                         span: source_span,
                         ty: &ty,
                         scope_span,
+                        expr: expr.map(|e| e.hir_id),
                     })
                     .or_insert(entries);
             }
@@ -163,17 +165,25 @@
     // which means that none of the regions inside relate to any other, even if
     // typeck had previously found constraints that would cause them to be related.
     let mut counter = 0;
-    let types = fcx.tcx.fold_regions(&types, &mut false, |_, current_depth| {
+    let fold_types: Vec<_> = types.iter().map(|(t, _)| t.ty).collect();
+    let folded_types = fcx.tcx.fold_regions(&fold_types, &mut false, |_, current_depth| {
         counter += 1;
         fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
     });
 
     // Store the generator types and spans into the tables for this generator.
-    let interior_types = types.iter().map(|t| t.0.clone()).collect::<Vec<_>>();
-    visitor.fcx.inh.tables.borrow_mut().generator_interior_types = interior_types;
+    let types = types
+        .into_iter()
+        .zip(&folded_types)
+        .map(|((mut interior_cause, _), ty)| {
+            interior_cause.ty = ty;
+            interior_cause
+        })
+        .collect();
+    visitor.fcx.inh.tables.borrow_mut().generator_interior_types = types;
 
     // Extract type components
-    let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| (t.0).ty));
+    let type_list = fcx.tcx.mk_type_list(folded_types.iter());
 
     let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
 
@@ -193,7 +203,9 @@
 // librustc/middle/region.rs since `expr_count` is compared against the results
 // there.
 impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -210,8 +222,6 @@
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-
         match &expr.kind {
             ExprKind::Call(callee, args) => match &callee.kind {
                 ExprKind::Path(qpath) => {
@@ -237,20 +247,13 @@
                 }
                 _ => intravisit::walk_expr(self, expr),
             },
-            ExprKind::Path(qpath) => {
-                let res = self.fcx.tables.borrow().qpath_res(qpath, expr.hir_id);
-                if let Res::Def(DefKind::Static, def_id) = res {
-                    // Statics are lowered to temporary references or
-                    // pointers in MIR, so record that type.
-                    let ptr_ty = self.fcx.tcx.static_ptr_ty(def_id);
-                    self.record(ptr_ty, scope, Some(expr), expr.span);
-                }
-            }
             _ => intravisit::walk_expr(self, expr),
         }
 
         self.expr_count += 1;
 
+        let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
+
         // If there are adjustments, then record the final type --
         // this is the actual value that is being produced.
         if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) {
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index a267b97..3572eda 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -2,17 +2,15 @@
 //! intrinsics that the compiler exposes.
 
 use crate::require_same_types;
+
 use rustc::traits::{ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
-
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::abi::Abi;
 
-use rustc_hir as hir;
-
-use rustc_error_codes::*;
-
 use std::iter;
 
 fn equate_intrinsic_type<'tcx>(
@@ -413,19 +411,20 @@
                 (2, params, param(1))
             }
             Err(_) => {
-                span_err!(
+                struct_span_err!(
                     tcx.sess,
                     it.span,
                     E0439,
                     "invalid `simd_shuffle`, needs length: `{}`",
                     name
-                );
+                )
+                .emit();
                 return;
             }
         },
         _ => {
             let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name);
-            tcx.sess.span_err(it.span, &msg);
+            tcx.sess.struct_span_err(it.span, &msg).emit();
             return;
         }
     };
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 636ea5b..2012a2a 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -569,7 +569,7 @@
 
         traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
             .filter_map(|predicate| match predicate {
-                ty::Predicate::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => {
+                ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
                     Some(trait_pred)
                 }
                 _ => None,
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index e9356a0..c1cf352 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -12,14 +12,14 @@
 
 use crate::check::FnCtxt;
 use crate::namespace::Namespace;
-use errors::{Applicability, DiagnosticBuilder};
 use rustc::infer::{self, InferOk};
 use rustc::traits;
 use rustc::ty::subst::Subst;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::GenericParamDefKind;
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness};
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind};
 use rustc_hir::def_id::DefId;
@@ -322,7 +322,7 @@
             span,
             self.body_id,
             self.param_env,
-            poly_trait_ref.to_predicate(),
+            poly_trait_ref.without_const().to_predicate(),
         );
 
         // Now we want to know if this can be matched
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 50f22ea..2adf125 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -25,9 +25,11 @@
 use rustc::ty::GenericParamDefKind;
 use rustc::ty::{
     self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
+    WithConstness,
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
 use std::cmp::max;
@@ -37,8 +39,6 @@
 use syntax::ast;
 use syntax::util::lev_distance::{find_best_match_for_name, lev_distance};
 
-use rustc_error_codes::*;
-
 use smallvec::{smallvec, SmallVec};
 
 use self::CandidateKind::*;
@@ -373,13 +373,14 @@
                 // so we do a future-compat lint here for the 2015 edition
                 // (see https://github.com/rust-lang/rust/issues/46906)
                 if self.tcx.sess.rust_2018() {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         span,
                         E0699,
                         "the type of this value must be known \
                                to call a method on a raw pointer on it"
-                    );
+                    )
+                    .emit();
                 } else {
                     self.tcx.lint_hir(
                         lint::builtin::TYVAR_BEHIND_RAW_POINTER,
@@ -824,7 +825,7 @@
         // FIXME: do we want to commit to this behavior for param bounds?
 
         let bounds = self.param_env.caller_bounds.iter().filter_map(|predicate| match *predicate {
-            ty::Predicate::Trait(ref trait_predicate) => {
+            ty::Predicate::Trait(ref trait_predicate, _) => {
                 match trait_predicate.skip_binder().trait_ref.self_ty().kind {
                     ty::Param(ref p) if *p == param_ty => Some(trait_predicate.to_poly_trait_ref()),
                     _ => None,
@@ -1394,7 +1395,7 @@
                 }
 
                 TraitCandidate(trait_ref) => {
-                    let predicate = trait_ref.to_predicate();
+                    let predicate = trait_ref.without_const().to_predicate();
                     let obligation = traits::Obligation::new(cause, self.param_env, predicate);
                     if !self.predicate_may_hold(&obligation) {
                         if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
@@ -1428,7 +1429,7 @@
                 let o = self.resolve_vars_if_possible(&o);
                 if !self.predicate_may_hold(&o) {
                     result = ProbeResult::NoMatch;
-                    if let &ty::Predicate::Trait(ref pred) = &o.predicate {
+                    if let &ty::Predicate::Trait(ref pred, _) = &o.predicate {
                         possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);
                     }
                 }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 1cc1eb2..e9942fa 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -4,24 +4,23 @@
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
 use crate::namespace::Namespace;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
-use rustc::hir::intravisit;
 use rustc::hir::map as hir_map;
+use rustc::hir::map::Map;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Obligation;
 use rustc::ty::print::with_crate_prefix;
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_span::{source_map, FileName, Span};
 use syntax::ast;
 use syntax::util::lev_distance;
 
-use rustc_error_codes::*;
-
 use std::cmp::Ordering;
 
 use super::probe::Mode;
@@ -58,7 +57,7 @@
                             span,
                             self.body_id,
                             self.param_env,
-                            poly_trait_ref.to_predicate(),
+                            poly_trait_ref.without_const().to_predicate(),
                         );
                         self.predicate_may_hold(&obligation)
                     })
@@ -193,21 +192,19 @@
                         let item_span =
                             self.tcx.sess.source_map().def_span(self.tcx.def_span(item.def_id));
                         let idx = if sources.len() > 1 {
-                            span_note!(
-                                err,
-                                item_span,
+                            let msg = &format!(
                                 "candidate #{} is defined in the trait `{}`",
                                 idx + 1,
                                 self.tcx.def_path_str(trait_did)
                             );
+                            err.span_note(item_span, msg);
                             Some(idx + 1)
                         } else {
-                            span_note!(
-                                err,
-                                item_span,
+                            let msg = &format!(
                                 "the candidate is defined in the trait `{}`",
                                 self.tcx.def_path_str(trait_did)
                             );
+                            err.span_note(item_span, msg);
                             None
                         };
                         let path = self.tcx.def_path_str(trait_did);
@@ -361,10 +358,11 @@
                             tcx.sess,
                             span,
                             E0599,
-                            "no {} named `{}` found for type `{}` in the current scope",
+                            "no {} named `{}` found for {} `{}` in the current scope",
                             item_kind,
                             item_name,
-                            ty_str
+                            actual.prefix_string(),
+                            ty_str,
                         );
                         if let Some(span) =
                             tcx.sess.confused_type_with_std_module.borrow().get(&span)
@@ -479,7 +477,7 @@
                     macro_rules! report_function {
                         ($span:expr, $name:expr) => {
                             err.note(&format!(
-                                "{} is a function, perhaps you wish to call it",
+                                "`{}` is a function, perhaps you wish to call it",
                                 $name
                             ));
                         };
@@ -1126,7 +1124,9 @@
         }
     }
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         intravisit::NestedVisitorMap::None
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 647c561..2dc198b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -90,8 +90,8 @@
 use crate::astconv::{AstConv, PathSeg};
 use crate::middle::lang_items;
 use crate::namespace::Namespace;
-use errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::blocks::FnLikeNode;
+use rustc::hir::map::Map;
 use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc::infer::opaque_types::OpaqueTypeDecl;
@@ -100,6 +100,7 @@
 use rustc::infer::{self, InferCtxt, InferOk, InferResult};
 use rustc::middle::region;
 use rustc::mir::interpret::ConstValue;
+use rustc::session::parse::feature_err;
 use rustc::traits::error_reporting::recursive_type_with_infinite_size_error;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::adjustment::{
@@ -112,14 +113,17 @@
 use rustc::ty::util::{Discr, IntTypeExt, Representability};
 use rustc::ty::{
     self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef,
-    ToPredicate, Ty, TyCtxt, UserType,
+    ToPredicate, Ty, TyCtxt, UserType, WithConstness,
 };
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
+use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath};
 use rustc_index::vec::Idx;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{original_sp, DUMMY_SP};
@@ -128,11 +132,8 @@
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::feature_gate::feature_err;
 use syntax::util::parser::ExprPrecedence;
 
-use rustc_error_codes::*;
-
 use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::cmp;
 use std::collections::hash_map::Entry;
@@ -145,7 +146,6 @@
 use crate::require_c_abi_if_c_variadic;
 use crate::session::config::EntryFnType;
 use crate::session::Session;
-use crate::util::captures::Captures;
 use crate::util::common::{indenter, ErrorReported};
 use crate::TypeAndSubsts;
 
@@ -157,6 +157,17 @@
 pub use self::Expectation::*;
 use self::TupleArgumentsFlag::*;
 
+#[macro_export]
+macro_rules! type_error_struct {
+    ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
+        if $typ.references_error() {
+            $session.diagnostic().struct_dummy()
+        } else {
+            rustc_errors::struct_span_err!($session, $span, $code, $($message)*)
+        }
+    })
+}
+
 /// The type of a local binding, including the revealed type for anon types.
 #[derive(Copy, Clone, Debug)]
 pub struct LocalTy<'tcx> {
@@ -1159,7 +1170,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1409,7 +1422,7 @@
                 inherited.register_predicate(traits::Obligation::new(
                     cause,
                     param_env,
-                    trait_ref.to_predicate(),
+                    trait_ref.without_const().to_predicate(),
                 ));
             }
         }
@@ -1650,7 +1663,7 @@
         if let hir::OpaqueTyOrigin::AsyncFn = origin {
             struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing",)
                 .span_label(span, "recursive `async fn`")
-                .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`.")
+                .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
                 .emit();
         } else {
             let mut err =
@@ -1695,17 +1708,11 @@
             check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
         }
         hir::ItemKind::Fn(..) => {} // entirely within check_item_body
-        hir::ItemKind::Impl(.., ref impl_item_refs) => {
+        hir::ItemKind::Impl { ref items, .. } => {
             debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
             let impl_def_id = tcx.hir().local_def_id(it.hir_id);
             if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
-                check_impl_items_against_trait(
-                    tcx,
-                    it.span,
-                    impl_def_id,
-                    impl_trait_ref,
-                    impl_item_refs,
-                );
+                check_impl_items_against_trait(tcx, it.span, impl_def_id, impl_trait_ref, items);
                 let trait_def_id = impl_trait_ref.def_id;
                 check_on_unimplemented(tcx, trait_def_id, it);
             }
@@ -2091,7 +2098,7 @@
 
     if !invalidated_items.is_empty() {
         let invalidator = overridden_associated_type.unwrap();
-        span_err!(
+        struct_span_err!(
             tcx.sess,
             invalidator.span,
             E0399,
@@ -2099,6 +2106,7 @@
             invalidator.ident,
             invalidated_items.iter().map(|name| name.to_string()).collect::<Vec<_>>().join("`, `")
         )
+        .emit();
     }
 }
 
@@ -2241,7 +2249,7 @@
         if def.is_struct() {
             let fields = &def.non_enum_variant().fields;
             if fields.is_empty() {
-                span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
+                struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
                 return;
             }
             let e = fields[0].ty(tcx, substs);
@@ -2255,12 +2263,13 @@
                 ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
                 _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         sp,
                         E0077,
                         "SIMD vector element type should be machine type"
-                    );
+                    )
+                    .emit();
                     return;
                 }
             }
@@ -2296,44 +2305,81 @@
                 "type has conflicting packed and align representation hints"
             )
             .emit();
-        } else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
-            struct_span_err!(
-                tcx.sess,
-                sp,
-                E0588,
-                "packed type cannot transitively contain a `[repr(align)]` type"
-            )
-            .emit();
+        } else {
+            if let Some(def_spans) = check_packed_inner(tcx, def_id, &mut vec![]) {
+                let mut err = struct_span_err!(
+                    tcx.sess,
+                    sp,
+                    E0588,
+                    "packed type cannot transitively contain a `#[repr(align)]` type"
+                );
+
+                let hir = tcx.hir();
+                if let Some(hir_id) = hir.as_local_hir_id(def_spans[0].0) {
+                    if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
+                        err.span_note(
+                            tcx.def_span(def_spans[0].0),
+                            &format!("`{}` has a `#[repr(align)]` attribute", ident),
+                        );
+                    }
+                }
+
+                if def_spans.len() > 2 {
+                    let mut first = true;
+                    for (adt_def, span) in def_spans.iter().skip(1).rev() {
+                        if let Some(hir_id) = hir.as_local_hir_id(*adt_def) {
+                            if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
+                                err.span_note(
+                                    *span,
+                                    &if first {
+                                        format!(
+                                            "`{}` contains a field of type `{}`",
+                                            tcx.type_of(def_id),
+                                            ident
+                                        )
+                                    } else {
+                                        format!("...which contains a field of type `{}`", ident)
+                                    },
+                                );
+                                first = false;
+                            }
+                        }
+                    }
+                }
+
+                err.emit();
+            }
         }
     }
 }
 
-fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
-    let t = tcx.type_of(def_id);
-    if stack.contains(&def_id) {
-        debug!("check_packed_inner: {:?} is recursive", t);
-        return false;
-    }
-    if let ty::Adt(def, substs) = t.kind {
+fn check_packed_inner(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    stack: &mut Vec<DefId>,
+) -> Option<Vec<(DefId, Span)>> {
+    if let ty::Adt(def, substs) = tcx.type_of(def_id).kind {
         if def.is_struct() || def.is_union() {
-            if tcx.adt_def(def.did).repr.align.is_some() {
-                return true;
+            if def.repr.align.is_some() {
+                return Some(vec![(def.did, DUMMY_SP)]);
             }
-            // push struct def_id before checking fields
+
             stack.push(def_id);
             for field in &def.non_enum_variant().fields {
-                let f = field.ty(tcx, substs);
-                if let ty::Adt(def, _) = f.kind {
-                    if check_packed_inner(tcx, def.did, stack) {
-                        return true;
+                if let ty::Adt(def, _) = field.ty(tcx, substs).kind {
+                    if !stack.contains(&def.did) {
+                        if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) {
+                            defs.push((def.did, field.ident.span));
+                            return Some(defs);
+                        }
                     }
                 }
             }
-            // only need to pop if not early out
             stack.pop();
         }
     }
-    false
+
+    None
 }
 
 /// Emit an error when encountering more or less than one variant in a transparent enum.
@@ -2545,14 +2591,15 @@
 }
 
 fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &QPath<'_>) {
-    span_err!(
+    struct_span_err!(
         tcx.sess,
         span,
         E0533,
         "expected unit struct, unit variant or constant, found {} `{}`",
         res.descr(),
         hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))
-    );
+    )
+    .emit();
 }
 
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
@@ -2564,6 +2611,16 @@
         None
     }
 
+    fn default_constness_for_trait_bounds(&self) -> ast::Constness {
+        // FIXME: refactor this into a method
+        let node = self.tcx.hir().get(self.body_id);
+        if let Some(fn_like) = FnLikeNode::from_node(node) {
+            fn_like.constness()
+        } else {
+            ast::Constness::NotConst
+        }
+    }
+
     fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
         let tcx = self.tcx;
         let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -2575,7 +2632,7 @@
             parent: None,
             predicates: tcx.arena.alloc_from_iter(self.param_env.caller_bounds.iter().filter_map(
                 |&predicate| match predicate {
-                    ty::Predicate::Trait(ref data)
+                    ty::Predicate::Trait(ref data, _)
                         if data.skip_binder().self_ty().is_param(index) =>
                     {
                         // HACK(eddyb) should get the original `Span`.
@@ -3647,7 +3704,7 @@
                 ty::Predicate::Projection(ref data) => {
                     Some((data.to_poly_trait_ref(self.tcx), obligation))
                 }
-                ty::Predicate::Trait(ref data) => Some((data.to_poly_trait_ref(), obligation)),
+                ty::Predicate::Trait(ref data, _) => Some((data.to_poly_trait_ref(), obligation)),
                 ty::Predicate::Subtype(..) => None,
                 ty::Predicate::RegionOutlives(..) => None,
                 ty::Predicate::TypeOutlives(..) => None,
@@ -3762,13 +3819,14 @@
                     arg_types.iter().map(|k| k.expect_ty()).collect()
                 }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         sp,
                         E0059,
                         "cannot use call notation; the first type parameter \
                          for the function trait is neither a tuple nor unit"
-                    );
+                    )
+                    .emit();
                     expected_arg_tys = vec![];
                     self.err_args(args.len())
                 }
@@ -3949,7 +4007,7 @@
                 continue;
             }
 
-            if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
+            if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate {
                 // Collect the argument position for all arguments that could have caused this
                 // `FulfillmentError`.
                 let mut referenced_in = final_arg_types
@@ -3993,7 +4051,7 @@
             if let hir::ExprKind::Path(qpath) = &path.kind {
                 if let hir::QPath::Resolved(_, path) = &qpath {
                     for error in errors {
-                        if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
+                        if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate {
                             // If any of the type arguments in this path segment caused the
                             // `FullfillmentError`, point at its span (#61860).
                             for arg in path
@@ -4371,10 +4429,8 @@
         self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
 
         // Hide the outer diverging and `has_errors` flags.
-        let old_diverges = self.diverges.get();
-        let old_has_errors = self.has_errors.get();
-        self.diverges.set(Diverges::Maybe);
-        self.has_errors.set(false);
+        let old_diverges = self.diverges.replace(Diverges::Maybe);
+        let old_has_errors = self.has_errors.replace(false);
 
         match stmt.kind {
             hir::StmtKind::Local(ref l) => {
@@ -4384,7 +4440,6 @@
             hir::StmtKind::Item(_) => {}
             hir::StmtKind::Expr(ref expr) => {
                 // Check with expected type of `()`.
-
                 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
                     self.suggest_semicolon_at_end(expr.span, err);
                 });
@@ -4728,14 +4783,13 @@
                         .join(", ");
                 }
                 Some(Node::Expr(hir::Expr {
-                    kind: ExprKind::Closure(_, _, body_id, closure_span, _),
+                    kind: ExprKind::Closure(_, _, body_id, _, _),
                     span: full_closure_span,
                     ..
                 })) => {
                     if *full_closure_span == expr.span {
                         return false;
                     }
-                    err.span_label(*closure_span, "closure defined here");
                     msg = "call this closure";
                     let body = hir.body(*body_id);
                     sugg_call = body
@@ -4935,9 +4989,8 @@
                 | ExprKind::Loop(..)
                 | ExprKind::Match(..)
                 | ExprKind::Block(..) => {
-                    let sp = self.tcx.sess.source_map().next_point(cause_span);
                     err.span_suggestion(
-                        sp,
+                        cause_span.shrink_to_hi(),
                         "try adding a semicolon",
                         ";".to_string(),
                         Applicability::MachineApplicable,
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 691469e..91e1731 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -2,17 +2,15 @@
 
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs};
-use errors::{self, Applicability};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint};
 use rustc::ty::{self, Ty, TypeFoldable};
+use rustc_errors::{self, struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_span::Span;
 use syntax::ast::Ident;
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Checks a `a <op>= b`
     pub fn check_binop_assign(
@@ -279,7 +277,7 @@
                                             lhs_expr.span,
                                             msg,
                                             format!("*{}", lstring),
-                                            errors::Applicability::MachineApplicable,
+                                            rustc_errors::Applicability::MachineApplicable,
                                         );
                                         suggested_deref = true;
                                     }
@@ -330,7 +328,7 @@
                                     Some("std::ops::Add"),
                                 ),
                                 hir::BinOpKind::Sub => (
-                                    format!("cannot substract `{}` from `{}`", rhs_ty, lhs_ty),
+                                    format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty),
                                     Some("std::ops::Sub"),
                                 ),
                                 hir::BinOpKind::Mul => (
@@ -482,7 +480,7 @@
     /// suggest calling the function. Returns wether a suggestion was given.
     fn add_type_neq_err_label(
         &self,
-        err: &mut errors::DiagnosticBuilder<'_>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_>,
         span: Span,
         ty: Ty<'tcx>,
         other_ty: Ty<'tcx>,
@@ -565,7 +563,7 @@
         rhs_expr: &'tcx hir::Expr<'tcx>,
         lhs_ty: Ty<'tcx>,
         rhs_ty: Ty<'tcx>,
-        err: &mut errors::DiagnosticBuilder<'_>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_>,
         is_assign: bool,
         op: hir::BinOp,
     ) -> bool {
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 051bf61..f9dee0e 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1,11 +1,11 @@
 use crate::check::FnCtxt;
-use errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Pattern;
 use rustc::ty::subst::GenericArg;
 use rustc::ty::{self, BindingMode, Ty, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -15,8 +15,6 @@
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
-
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 
@@ -135,12 +133,7 @@
         let ty = match pat.kind {
             PatKind::Wild => expected,
             PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
-            PatKind::Range(begin, end, _) => {
-                match self.check_pat_range(pat.span, begin, end, expected, ti) {
-                    None => return,
-                    Some(ty) => ty,
-                }
-            }
+            PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
             PatKind::Binding(ba, var_id, _, sub) => {
                 self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti)
             }
@@ -395,39 +388,49 @@
     fn check_pat_range(
         &self,
         span: Span,
-        lhs: &'tcx hir::Expr<'tcx>,
-        rhs: &'tcx hir::Expr<'tcx>,
+        lhs: Option<&'tcx hir::Expr<'tcx>>,
+        rhs: Option<&'tcx hir::Expr<'tcx>>,
         expected: Ty<'tcx>,
         ti: TopInfo<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        let lhs_ty = self.check_expr(lhs);
-        let rhs_ty = self.check_expr(rhs);
+    ) -> Ty<'tcx> {
+        let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
+            None => (None, None),
+            Some(expr) => {
+                let ty = self.check_expr(expr);
+                // Check that the end-point is of numeric or char type.
+                let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error());
+                (Some(ty), Some((fail, ty, expr.span)))
+            }
+        };
+        let (lhs_ty, lhs) = calc_side(lhs);
+        let (rhs_ty, rhs) = calc_side(rhs);
 
-        // Check that both end-points are of numeric or char type.
-        let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char() || ty.references_error();
-        let lhs_fail = !numeric_or_char(lhs_ty);
-        let rhs_fail = !numeric_or_char(rhs_ty);
-
-        if lhs_fail || rhs_fail {
-            self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
-            return None;
+        if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
+            // There exists a side that didn't meet our criteria that the end-point
+            // be of a numeric or char type, as checked in `calc_side` above.
+            self.emit_err_pat_range(span, lhs, rhs);
+            return self.tcx.types.err;
         }
 
-        // Now that we know the types can be unified we find the unified type and use
-        // it to type the entire expression.
-        let common_type = self.resolve_vars_if_possible(&lhs_ty);
+        // Now that we know the types can be unified we find the unified type
+        // and use it to type the entire expression.
+        let common_type = self.resolve_vars_if_possible(&lhs_ty.or(rhs_ty).unwrap_or(expected));
 
         // Subtyping doesn't matter here, as the value is some kind of scalar.
-        let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
-            self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
-                self.endpoint_has_type(&mut err, y_span, y_ty);
-                err.emit();
-            });
+        let demand_eqtype = |x, y| {
+            if let Some((_, x_ty, x_span)) = x {
+                self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
+                    if let Some((_, y_ty, y_span)) = y {
+                        self.endpoint_has_type(&mut err, y_span, y_ty);
+                    }
+                    err.emit();
+                });
+            }
         };
-        demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty);
-        demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty);
+        demand_eqtype(lhs, rhs);
+        demand_eqtype(rhs, lhs);
 
-        Some(common_type)
+        common_type
     }
 
     fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
@@ -439,21 +442,15 @@
     fn emit_err_pat_range(
         &self,
         span: Span,
-        begin_span: Span,
-        end_span: Span,
-        lhs_fail: bool,
-        rhs_fail: bool,
-        lhs_ty: Ty<'tcx>,
-        rhs_ty: Ty<'tcx>,
+        lhs: Option<(bool, Ty<'tcx>, Span)>,
+        rhs: Option<(bool, Ty<'tcx>, Span)>,
     ) {
-        let span = if lhs_fail && rhs_fail {
-            span
-        } else if lhs_fail {
-            begin_span
-        } else {
-            end_span
+        let span = match (lhs, rhs) {
+            (Some((true, ..)), Some((true, ..))) => span,
+            (Some((true, _, sp)), _) => sp,
+            (_, Some((true, _, sp))) => sp,
+            _ => span_bug!(span, "emit_err_pat_range: no side failed or exists but still error?"),
         };
-
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
@@ -461,17 +458,20 @@
             "only char and numeric types are allowed in range patterns"
         );
         let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
-        let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
+        let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
             err.span_label(first_span, &msg(first_ty));
-            self.endpoint_has_type(&mut err, second_span, second_ty);
+            if let Some((_, ty, sp)) = second {
+                self.endpoint_has_type(&mut err, sp, ty);
+            }
         };
-        if lhs_fail && rhs_fail {
-            err.span_label(begin_span, &msg(lhs_ty));
-            err.span_label(end_span, &msg(rhs_ty));
-        } else if lhs_fail {
-            one_side_err(begin_span, lhs_ty, end_span, rhs_ty);
-        } else {
-            one_side_err(end_span, rhs_ty, begin_span, lhs_ty);
+        match (lhs, rhs) {
+            (Some((true, lhs_ty, lhs_sp)), Some((true, rhs_ty, rhs_sp))) => {
+                err.span_label(lhs_sp, &msg(lhs_ty));
+                err.span_label(rhs_sp, &msg(rhs_ty));
+            }
+            (Some((true, lhs_ty, lhs_sp)), rhs) => one_side_err(lhs_sp, lhs_ty, rhs),
+            (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
+            _ => span_bug!(span, "Impossible, verified above."),
         }
         if self.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
@@ -983,22 +983,25 @@
 
         // Require `..` if struct has non_exhaustive attribute.
         if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
-            span_err!(
+            struct_span_err!(
                 tcx.sess,
                 span,
                 E0638,
                 "`..` required with {} marked as non-exhaustive",
                 kind_name
-            );
+            )
+            .emit();
         }
 
         // Report an error if incorrect number of the fields were specified.
         if kind_name == "union" {
             if fields.len() != 1 {
-                tcx.sess.span_err(span, "union patterns should have exactly one field");
+                tcx.sess
+                    .struct_span_err(span, "union patterns should have exactly one field")
+                    .emit();
             }
             if etc {
-                tcx.sess.span_err(span, "`..` cannot be used in union patterns");
+                tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit();
             }
         } else if !etc && unmentioned_fields.len() > 0 {
             self.error_unmentioned_fields(span, &unmentioned_fields, variant);
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 3b2f3d1..9677410 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -76,7 +76,7 @@
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::{self, RegionObligation, SuppressRegionErrors};
 use rustc::ty::adjustment;
@@ -84,6 +84,7 @@
 use rustc::ty::{self, Ty};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::PatKind;
 use rustc_span::Span;
 use std::mem;
@@ -414,7 +415,9 @@
     // hierarchy, and in particular the relationships between free
     // regions, until regionck, as described in #3238.
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index be912b6..e4502bf 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -35,13 +35,14 @@
 use crate::expr_use_visitor as euv;
 use crate::mem_categorization as mc;
 use crate::mem_categorization::PlaceBase;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::infer::UpvarRegion;
 use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::Span;
 use syntax::ast;
 
@@ -59,7 +60,9 @@
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -209,7 +212,7 @@
         }
     }
 
-    // Returns a list of `ClosureUpvar`s for each upvar.
+    // Returns a list of `Ty`s for each upvar.
     fn final_upvar_tys(&self, closure_id: hir::HirId) -> Vec<Ty<'tcx>> {
         // Presently an unboxed closure type cannot "escape" out of a
         // function, so we will only encounter ones that originated in the
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index f3a51fa..8281182 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -3,24 +3,23 @@
 
 use rustc::infer::opaque_types::may_define_opaque_type;
 use rustc::middle::lang_items;
+use rustc::session::parse::feature_err;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{
+    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
-
-use errors::DiagnosticBuilder;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use syntax::ast;
-use syntax::feature_gate;
 
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 
-use rustc_error_codes::*;
-
 /// Helper type of a temporary returned by `.for_item(...)`.
 /// This is necessary because we can't write the following bound:
 ///
@@ -98,7 +97,7 @@
         //
         // won't be allowed unless there's an *explicit* implementation of `Send`
         // for `T`
-        hir::ItemKind::Impl(_, _, defaultness, _, ref trait_ref, ref self_ty, _) => {
+        hir::ItemKind::Impl { defaultness, ref of_trait, ref self_ty, .. } => {
             let is_auto = tcx
                 .impl_trait_ref(tcx.hir().local_def_id(item.hir_id))
                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
@@ -108,18 +107,19 @@
             }
             match polarity {
                 ty::ImplPolarity::Positive => {
-                    check_impl(tcx, item, self_ty, trait_ref);
+                    check_impl(tcx, item, self_ty, of_trait);
                 }
                 ty::ImplPolarity::Negative => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
-                    if trait_ref.is_some() && !is_auto {
-                        span_err!(
+                    if of_trait.is_some() && !is_auto {
+                        struct_span_err!(
                             tcx.sess,
                             item.span,
                             E0192,
                             "negative impls are only allowed for \
                                    auto traits (e.g., `Send` and `Sync`)"
                         )
+                        .emit()
                     }
                 }
                 ty::ImplPolarity::Reservation => {
@@ -821,7 +821,7 @@
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
             if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
                 // Report error; would have worked with `arbitrary_self_types`.
-                feature_gate::feature_err(
+                feature_err(
                     &fcx.tcx.sess.parse_sess,
                     sym::arbitrary_self_types,
                     span,
@@ -955,7 +955,8 @@
         substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
     };
 
-    let obligation = traits::Obligation::new(cause, fcx.param_env, trait_ref.to_predicate());
+    let obligation =
+        traits::Obligation::new(cause, fcx.param_env, trait_ref.without_const().to_predicate());
 
     if fcx.predicate_must_hold_modulo_regions(&obligation) {
         true
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index ad9a2f2..b4798fb 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -4,7 +4,7 @@
 
 use crate::check::FnCtxt;
 
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::Map;
 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc::infer::InferCtxt;
 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
@@ -13,6 +13,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdSet, DefIndex};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -242,7 +243,9 @@
 // traffic in node-ids or update tables in the type context etc.
 
 impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index ab8e4ce..ec098c1 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -1,15 +1,13 @@
 use crate::lint;
 use rustc::ty::TyCtxt;
-
-use errors::Applicability;
-use rustc_span::Span;
-use syntax::ast;
-
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::visibility_qualified;
+use rustc_span::Span;
+use syntax::ast;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports = DefIdSet::default();
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index eb1ea67..79a006a 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -1,25 +1,22 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
+use rustc::infer;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::SuppressRegionErrors;
 use rustc::middle::lang_items::UnsizeTraitLangItem;
 use rustc::middle::region;
-
-use rustc::infer;
 use rustc::traits::misc::{can_type_implement_copy, CopyImplementationError};
 use rustc::traits::predicate_for_trait_def;
 use rustc::traits::{self, ObligationCause, TraitEngine};
 use rustc::ty::adjustment::CoerceUnsizedInfo;
 use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt};
-
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
 
-use rustc_error_codes::*;
-
 pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
         .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
@@ -59,7 +56,7 @@
 
     let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).expect("foreign Drop impl on non-ADT");
     let sp = match tcx.hir().expect_item(impl_hir_id).kind {
-        ItemKind::Impl(.., ty, _) => ty.span,
+        ItemKind::Impl { self_ty, .. } => self_ty.span,
         _ => bug!("expected Drop impl item"),
     };
 
@@ -96,7 +93,7 @@
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
             let item = tcx.hir().expect_item(impl_hir_id);
-            let span = if let ItemKind::Impl(.., Some(ref tr), _, _) = item.kind {
+            let span = if let ItemKind::Impl { of_trait: Some(ref tr), .. } = item.kind {
                 tr.path.span
             } else {
                 span
@@ -115,7 +112,8 @@
         }
         Err(CopyImplementationError::NotAnAdt) => {
             let item = tcx.hir().expect_item(impl_hir_id);
-            let span = if let ItemKind::Impl(.., ref ty, _) = item.kind { ty.span } else { span };
+            let span =
+                if let ItemKind::Impl { self_ty, .. } = item.kind { self_ty.span } else { span };
 
             struct_span_err!(
                 tcx.sess,
@@ -393,7 +391,7 @@
                 if def_a != def_b {
                     let source_path = tcx.def_path_str(def_a.did);
                     let target_path = tcx.def_path_str(def_b.did);
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0377,
@@ -402,7 +400,8 @@
                                definition; expected `{}`, found `{}`",
                         source_path,
                         target_path
-                    );
+                    )
+                    .emit();
                     return err_info;
                 }
 
@@ -479,36 +478,37 @@
                     .collect::<Vec<_>>();
 
                 if diff_fields.is_empty() {
-                    span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0374,
                         "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures with one field \
                                being coerced, none found"
-                    );
+                    )
+                    .emit();
                     return err_info;
                 } else if diff_fields.len() > 1 {
                     let item = tcx.hir().expect_item(impl_hir_id);
-                    let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.kind {
+                    let span = if let ItemKind::Impl { of_trait: Some(ref t), .. } = item.kind {
                         t.path.span
                     } else {
                         tcx.hir().span(impl_hir_id)
                     };
 
-                    let mut err = struct_span_err!(
+                    struct_span_err!(
                         tcx.sess,
                         span,
                         E0375,
                         "implementing the trait \
                                                     `CoerceUnsized` requires multiple \
                                                     coercions"
-                    );
-                    err.note(
+                    )
+                    .note(
                         "`CoerceUnsized` may only be implemented for \
                               a coercion between structures with one field being coerced",
-                    );
-                    err.note(&format!(
+                    )
+                    .note(&format!(
                         "currently, {} fields need coercions: {}",
                         diff_fields.len(),
                         diff_fields
@@ -518,9 +518,9 @@
                             })
                             .collect::<Vec<_>>()
                             .join(", ")
-                    ));
-                    err.span_label(span, "requires multiple coercions");
-                    err.emit();
+                    ))
+                    .span_label(span, "requires multiple coercions")
+                    .emit();
                     return err_info;
                 }
 
@@ -530,13 +530,14 @@
             }
 
             _ => {
-                span_err!(
+                struct_span_err!(
                     tcx.sess,
                     span,
                     E0376,
                     "the trait `CoerceUnsized` may only be implemented \
                            for a coercion between structures"
-                );
+                )
+                .emit();
                 return err_info;
             }
         };
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 76de177..d4c89b7 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -8,6 +8,7 @@
 //! is computed by selecting an idea from this table.
 
 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -15,8 +16,6 @@
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
 pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> &CrateInherentImpls {
     assert_eq!(crate_num, LOCAL_CRATE);
@@ -46,7 +45,7 @@
 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         let ty = match item.kind {
-            hir::ItemKind::Impl(.., None, ref ty, _) => ty,
+            hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty,
             _ => return,
         };
 
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index fed8ed5..d60c3cf 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -1,12 +1,11 @@
 use crate::namespace::Namespace;
 use rustc::traits::{self, IntercrateMode};
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
-use rustc_error_codes::*;
-
 pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
     assert_eq!(crate_num, LOCAL_CRATE);
     let krate = tcx.hir().krate();
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 2d19b73..5583e34 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -5,13 +5,12 @@
 // done by the orphan and overlap modules. Then we build up various
 // mappings. That mapping code resides here.
 
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
-use crate::hir::HirId;
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
-
-use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::HirId;
 
 mod builtin;
 mod inherent_impls;
@@ -145,8 +144,8 @@
         tcx.ensure().coherent_trait(trait_def_id);
     }
 
-    tcx.sess.time("unsafety checking", || unsafety::check(tcx));
-    tcx.sess.time("orphan checking", || orphan::check(tcx));
+    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
+    tcx.sess.time("orphan_checking", || orphan::check(tcx));
 
     // these queries are executed for side-effects (error reporting):
     tcx.ensure().crate_inherent_impls(LOCAL_CRATE);
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 8a87bca..8052166 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -3,11 +3,10 @@
 
 use rustc::traits;
 use rustc::ty::{self, TyCtxt};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
-use rustc_error_codes::*;
-
 pub fn check(tcx: TyCtxt<'_>) {
     let mut orphan = OrphanChecker { tcx };
     tcx.hir().krate().visit_all_item_likes(&mut orphan);
@@ -26,7 +25,7 @@
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         let def_id = self.tcx.hir().local_def_id(item.hir_id);
         // "Trait" impl
-        if let hir::ItemKind::Impl(.., generics, Some(tr), impl_ty, _) = &item.kind {
+        if let hir::ItemKind::Impl { generics, of_trait: Some(ref tr), self_ty, .. } = &item.kind {
             debug!(
                 "coherence2::orphan check: trait impl {}",
                 self.tcx.hir().node_to_string(item.hir_id)
@@ -71,7 +70,7 @@
                         let msg = format!("{} is not defined in the current crate{}", ty, postfix);
                         if *is_target_ty {
                             // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
-                            err.span_label(impl_ty.span, &msg);
+                            err.span_label(self_ty.span, &msg);
                         } else {
                             // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
                             err.span_label(tr.path.span, &msg);
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index ed0d9ba..a604421 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -2,12 +2,11 @@
 //! crate or pertains to a type defined in this crate.
 
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Unsafety;
 
-use rustc_error_codes::*;
-
 pub fn check(tcx: TyCtxt<'_>) {
     let mut unsafety = UnsafetyChecker { tcx };
     tcx.hir().krate().visit_all_item_likes(&mut unsafety);
@@ -33,23 +32,25 @@
             });
             match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
                 (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0199,
                         "implementing the trait `{}` is not unsafe",
                         trait_ref.print_only_trait_path()
-                    );
+                    )
+                    .emit();
                 }
 
                 (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0200,
                         "the trait `{}` requires an `unsafe impl` declaration",
                         trait_ref.print_only_trait_path()
-                    );
+                    )
+                    .emit();
                 }
 
                 (
@@ -58,13 +59,14 @@
                     Unsafety::Normal,
                     hir::ImplPolarity::Positive,
                 ) => {
-                    span_err!(
+                    struct_span_err!(
                         self.tcx.sess,
                         item.span,
                         E0569,
                         "requires an `unsafe impl` declaration due to `#[{}]` attribute",
                         attr_name
-                    );
+                    )
+                    .emit();
                 }
 
                 (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
@@ -84,7 +86,7 @@
 
 impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item<'v>) {
-        if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.kind {
+        if let hir::ItemKind::Impl { unsafety, polarity, ref generics, .. } = item.kind {
             self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
         }
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fb9e4ba..843872d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -20,22 +20,26 @@
 use crate::lint;
 use crate::middle::resolve_lifetime as rl;
 use crate::middle::weak_lang_items;
-use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::blocks::FnLikeNode;
+use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
+use rustc::session::parse::feature_err;
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::GenericArgKind;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::Discr;
 use rustc::ty::util::IntTypeExt;
-use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
+use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness};
 use rustc::ty::{ReprOptions, ToPredicate};
-use rustc::util::captures::Captures;
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, Applicability, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericParamKind, Node, Unsafety};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -43,11 +47,6 @@
 use syntax::ast;
 use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
-use syntax::feature_gate;
-
-use errors::{Applicability, StashKey};
-
-use rustc_error_codes::*;
 
 struct OnlySelfBounds(bool);
 
@@ -105,7 +104,9 @@
 crate struct PlaceholderHirTyCollector(crate Vec<Span>);
 
 impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
+    type Map = Map<'v>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::None
     }
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
@@ -125,7 +126,7 @@
 /// all already existing generic type parameters to avoid suggesting a name that is already in use.
 crate fn placeholder_type_error(
     tcx: TyCtxt<'tcx>,
-    ident_span: Span,
+    span: Span,
     generics: &[hir::GenericParam<'_>],
     placeholder_types: Vec<Span>,
     suggest: bool,
@@ -151,7 +152,14 @@
     let mut sugg: Vec<_> =
         placeholder_types.iter().map(|sp| (*sp, type_name.to_string())).collect();
     if generics.is_empty() {
-        sugg.push((ident_span.shrink_to_hi(), format!("<{}>", type_name)));
+        sugg.push((span, format!("<{}>", type_name)));
+    } else if let Some(arg) = generics.iter().find(|arg| match arg.name {
+        hir::ParamName::Plain(Ident { name: kw::Underscore, .. }) => true,
+        _ => false,
+    }) {
+        // Account for `_` already present in cases like `struct S<_>(_);` and suggest
+        // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
+        sugg.push((arg.span, format!("{}", type_name)));
     } else {
         sugg.push((
             generics.iter().last().unwrap().span.shrink_to_hi(),
@@ -173,8 +181,12 @@
     let (generics, suggest) = match &item.kind {
         hir::ItemKind::Union(_, generics)
         | hir::ItemKind::Enum(_, generics)
-        | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true),
-        hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false),
+        | hir::ItemKind::TraitAlias(generics, _)
+        | hir::ItemKind::Trait(_, _, generics, ..)
+        | hir::ItemKind::Impl { generics, .. }
+        | hir::ItemKind::Struct(_, generics) => (generics, true),
+        hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
+        | hir::ItemKind::TyAlias(_, generics) => (generics, false),
         // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
         _ => return,
     };
@@ -182,11 +194,13 @@
     let mut visitor = PlaceholderHirTyCollector::default();
     visitor.visit_item(item);
 
-    placeholder_type_error(tcx, item.ident.span, generics, visitor.0, suggest);
+    placeholder_type_error(tcx, generics.span, &generics.params[..], visitor.0, suggest);
 }
 
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
 
@@ -240,7 +254,7 @@
 fn bad_placeholder_type(
     tcx: TyCtxt<'tcx>,
     mut spans: Vec<Span>,
-) -> errors::DiagnosticBuilder<'tcx> {
+) -> rustc_errors::DiagnosticBuilder<'tcx> {
     spans.sort();
     let mut err = struct_span_err!(
         tcx.sess,
@@ -273,6 +287,22 @@
         Some(self.item_def_id)
     }
 
+    fn default_constness_for_trait_bounds(&self) -> ast::Constness {
+        // FIXME: refactor this into a method
+        let hir_id = self
+            .tcx
+            .hir()
+            .as_local_hir_id(self.item_def_id)
+            .expect("Non-local call to local provider is_const_fn");
+
+        let node = self.tcx.hir().get(hir_id);
+        if let Some(fn_like) = FnLikeNode::from_node(node) {
+            fn_like.constness()
+        } else {
+            ast::Constness::NotConst
+        }
+    }
+
     fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
         self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
     }
@@ -320,13 +350,14 @@
             self.tcx().mk_projection(item_def_id, item_substs)
         } else {
             // There are no late-bound regions; we can just ignore the binder.
-            span_err!(
+            struct_span_err!(
                 self.tcx().sess,
                 span,
                 E0212,
                 "cannot extract an associated type from a higher-ranked trait bound \
                  in this context"
-            );
+            )
+            .emit();
             self.tcx().types.err
         }
     }
@@ -385,7 +416,7 @@
         Node::Item(item) => {
             match item.kind {
                 ItemKind::Fn(.., ref generics, _)
-                | ItemKind::Impl(_, _, _, ref generics, ..)
+                | ItemKind::Impl { ref generics, .. }
                 | ItemKind::TyAlias(_, ref generics)
                 | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
                 | ItemKind::Enum(_, ref generics)
@@ -395,7 +426,8 @@
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_hir_id {
                         let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
-                        extend = Some((identity_trait_ref.to_predicate(), item.span));
+                        extend =
+                            Some((identity_trait_ref.without_const().to_predicate(), item.span));
                     }
                     generics
                 }
@@ -416,7 +448,7 @@
         icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
             .into_iter()
             .filter(|(predicate, _)| match predicate {
-                ty::Predicate::Trait(ref data) => data.skip_binder().self_ty().is_param(index),
+                ty::Predicate::Trait(ref data, _) => data.skip_binder().self_ty().is_param(index),
                 _ => false,
             }),
     );
@@ -437,6 +469,7 @@
         ty: Ty<'tcx>,
         only_self_bounds: OnlySelfBounds,
     ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+        let constness = self.default_constness_for_trait_bounds();
         let from_ty_params = ast_generics
             .params
             .iter()
@@ -445,7 +478,7 @@
                 _ => None,
             })
             .flat_map(|bounds| bounds.iter())
-            .flat_map(|b| predicates_from_bound(self, ty, b));
+            .flat_map(|b| predicates_from_bound(self, ty, b, constness));
 
         let from_where_clauses = ast_generics
             .where_clause
@@ -465,7 +498,7 @@
                 };
                 bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
             })
-            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
+            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -515,7 +548,7 @@
             tcx.predicates_of(def_id);
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
         }
-        hir::ItemKind::Impl(..) => {
+        hir::ItemKind::Impl { .. } => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.impl_trait_ref(def_id);
@@ -841,7 +874,7 @@
     // which will, in turn, reach indirect supertraits.
     for &(pred, span) in superbounds {
         debug!("superbound: {:?}", pred);
-        if let ty::Predicate::Trait(bound) = pred {
+        if let ty::Predicate::Trait(bound, _) = pred {
             tcx.at(span).super_predicates_of(bound.def_id());
         }
     }
@@ -861,17 +894,14 @@
 
     let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
     if paren_sugar && !tcx.features().unboxed_closures {
-        let mut err = tcx.sess.struct_span_err(
-            item.span,
-            "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
+        tcx.sess
+            .struct_span_err(
+                item.span,
+                "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
              which traits can use parenthetical notation",
-        );
-        help!(
-            &mut err,
-            "add `#![feature(unboxed_closures)]` to \
-             the crate attributes to use it"
-        );
-        err.emit();
+            )
+            .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")
+            .emit();
     }
 
     let is_marker = tcx.has_attr(def_id, sym::marker);
@@ -888,7 +918,9 @@
     }
 
     impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
-        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        type Map = Map<'tcx>;
+
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -1037,9 +1069,7 @@
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) => {
-                    generics
-                }
+                ItemKind::Fn(.., ref generics, _) | ItemKind::Impl { ref generics, .. } => generics,
 
                 ItemKind::TyAlias(_, ref generics)
                 | ItemKind::Enum(_, ref generics)
@@ -1206,12 +1236,13 @@
 }
 
 fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
-    span_err!(
+    struct_span_err!(
         tcx.sess,
         span,
         E0202,
         "associated types are not yet supported in inherent impls (see #8995)"
-    );
+    )
+    .emit();
 }
 
 fn infer_placeholder_type(
@@ -1322,7 +1353,9 @@
                         icx.to_ty(ty)
                     }
                 }
-                ItemKind::TyAlias(ref ty, _) | ItemKind::Impl(.., ref ty, _) => icx.to_ty(ty),
+                ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
+                    icx.to_ty(self_ty)
+                }
                 ItemKind::Fn(..) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_fn_def(def_id, substs)
@@ -1521,7 +1554,7 @@
                         _ => None,
                     };
                     if let Some(unsupported_type) = err {
-                        feature_gate::feature_err(
+                        feature_err(
                             &tcx.sess.parse_sess,
                             sym::const_compare_raw_pointers,
                             hir_ty.span,
@@ -1640,8 +1673,15 @@
                     ty::Param(_) => true,
                     _ => false,
                 };
-                let bad_substs: Vec<_> =
-                    substs.types().enumerate().filter(|(_, ty)| !is_param(ty)).collect();
+                let bad_substs: Vec<_> = substs
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(i, k)| {
+                        if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None }
+                    })
+                    .filter(|(_, ty)| !is_param(ty))
+                    .collect();
+
                 if !bad_substs.is_empty() {
                     let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id);
                     for (i, bad_subst) in bad_substs {
@@ -1717,7 +1757,9 @@
     }
 
     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
-        fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+        type Map = Map<'tcx>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
             intravisit::NestedVisitorMap::All(&self.tcx.hir())
         }
         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
@@ -1788,13 +1830,35 @@
     }
 }
 
+fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
+    generic_args
+        .iter()
+        .filter_map(|arg| match arg {
+            hir::GenericArg::Type(ty) => Some(ty),
+            _ => None,
+        })
+        .any(is_suggestable_infer_ty)
+}
+
 /// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
 /// use inference to provide suggestions for the appropriate type if possible.
 fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
+    use hir::TyKind::*;
     match &ty.kind {
-        hir::TyKind::Infer => true,
-        hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty),
-        hir::TyKind::Tup(tys) => tys.iter().any(|ty| is_suggestable_infer_ty(ty)),
+        Infer => true,
+        Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
+        Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
+        Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
+        Def(_, generic_args) => are_suggestable_generic_args(generic_args),
+        Path(hir::QPath::TypeRelative(ty, segment)) => {
+            is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.generic_args().args)
+        }
+        Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
+            ty_opt.map_or(false, is_suggestable_infer_ty)
+                || segments
+                    .iter()
+                    .any(|segment| are_suggestable_generic_args(segment.generic_args().args))
+        }
         _ => false,
     }
 }
@@ -1916,12 +1980,10 @@
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     match tcx.hir().expect_item(hir_id).kind {
-        hir::ItemKind::Impl(.., ref opt_trait_ref, _, _) => {
-            opt_trait_ref.as_ref().map(|ast_trait_ref| {
-                let selfty = tcx.type_of(def_id);
-                AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
-            })
-        }
+        hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| {
+            let selfty = tcx.type_of(def_id);
+            AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
+        }),
         _ => bug!(),
     }
 }
@@ -1931,19 +1993,21 @@
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
     let item = tcx.hir().expect_item(hir_id);
     match &item.kind {
-        hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => {
+        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => {
             if is_rustc_reservation {
                 tcx.sess.span_err(item.span, "reservation impls can't be negative");
             }
             ty::ImplPolarity::Negative
         }
-        hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => {
+        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
             if is_rustc_reservation {
                 tcx.sess.span_err(item.span, "reservation impls can't be inherent");
             }
             ty::ImplPolarity::Positive
         }
-        hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => {
+        hir::ItemKind::Impl {
+            polarity: hir::ImplPolarity::Positive, of_trait: Some(_), ..
+        } => {
             if is_rustc_reservation {
                 ty::ImplPolarity::Reservation
             } else {
@@ -2016,7 +2080,7 @@
         let span = tcx.def_span(def_id);
         result.predicates =
             tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
-                ty::TraitRef::identity(tcx, def_id).to_predicate(),
+                ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(),
                 span,
             ))));
     }
@@ -2066,6 +2130,7 @@
     let mut is_default_impl_trait = None;
 
     let icx = ItemCtxt::new(tcx, def_id);
+    let constness = icx.default_constness_for_trait_bounds();
 
     const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty();
 
@@ -2102,7 +2167,7 @@
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Impl(_, _, defaultness, ref generics, ..) => {
+                ItemKind::Impl { defaultness, ref generics, .. } => {
                     if defaultness.is_default() {
                         is_default_impl_trait = tcx.impl_trait_ref(def_id);
                     }
@@ -2190,7 +2255,10 @@
     // (see below). Recall that a default impl is not itself an impl, but rather a
     // set of defaults that can be incorporated into another impl.
     if let Some(trait_ref) = is_default_impl_trait {
-        predicates.push((trait_ref.to_poly_trait_ref().to_predicate(), tcx.def_span(def_id)));
+        predicates.push((
+            trait_ref.to_poly_trait_ref().without_const().to_predicate(),
+            tcx.def_span(def_id),
+        ));
     }
 
     // Collect the region predicates that were declared inline as
@@ -2264,11 +2332,18 @@
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
-                        &hir::GenericBound::Trait(ref poly_trait_ref, _) => {
+                        &hir::GenericBound::Trait(ref poly_trait_ref, modifier) => {
+                            let constness = match modifier {
+                                hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst,
+                                hir::TraitBoundModifier::None => constness,
+                                hir::TraitBoundModifier::Maybe => bug!("this wasn't handled"),
+                            };
+
                             let mut bounds = Bounds::default();
                             let _ = AstConv::instantiate_poly_trait_ref(
                                 &icx,
                                 poly_trait_ref,
+                                constness,
                                 ty,
                                 &mut bounds,
                             );
@@ -2319,7 +2394,7 @@
     // before uses of `U`.  This avoids false ambiguity errors
     // in trait checking. See `setup_constraining_predicates`
     // for details.
-    if let Node::Item(&Item { kind: ItemKind::Impl(..), .. }) = node {
+    if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
         let self_ty = tcx.type_of(def_id);
         let trait_ref = tcx.impl_trait_ref(def_id);
         cgp::setup_constraining_predicates(
@@ -2444,11 +2519,18 @@
     astconv: &dyn AstConv<'tcx>,
     param_ty: Ty<'tcx>,
     bound: &'tcx hir::GenericBound<'tcx>,
+    constness: ast::Constness,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     match *bound {
-        hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
+        hir::GenericBound::Trait(ref tr, modifier) => {
+            let constness = match modifier {
+                hir::TraitBoundModifier::Maybe => return vec![],
+                hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst,
+                hir::TraitBoundModifier::None => constness,
+            };
+
             let mut bounds = Bounds::default();
-            let _ = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut bounds);
+            let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds);
             bounds.predicates(astconv.tcx(), param_ty)
         }
         hir::GenericBound::Outlives(ref lifetime) => {
@@ -2456,7 +2538,6 @@
             let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
             vec![(ty::Predicate::TypeOutlives(pred), lifetime.span)]
         }
-        hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![],
     }
 }
 
@@ -2606,7 +2687,7 @@
                 None => true,
             };
             if !allowed && id.is_local() {
-                feature_gate::feature_err(
+                feature_err(
                     &tcx.sess.parse_sess,
                     feature_gate.unwrap(),
                     item.span(),
@@ -2767,14 +2848,26 @@
                 mark_used(attr);
                 inline_span = Some(attr.span);
                 if items.len() != 1 {
-                    span_err!(tcx.sess.diagnostic(), attr.span, E0534, "expected one argument");
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0534,
+                        "expected one argument"
+                    )
+                    .emit();
                     InlineAttr::None
                 } else if list_contains_name(&items[..], sym::always) {
                     InlineAttr::Always
                 } else if list_contains_name(&items[..], sym::never) {
                     InlineAttr::Never
                 } else {
-                    span_err!(tcx.sess.diagnostic(), items[0].span(), E0535, "invalid argument");
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        items[0].span(),
+                        E0535,
+                        "invalid argument"
+                    )
+                    .emit();
 
                     InlineAttr::None
                 }
@@ -2788,7 +2881,7 @@
         if !attr.has_name(sym::optimize) {
             return ia;
         }
-        let err = |sp, s| span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s);
+        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
         match attr.meta().map(|i| i.kind) {
             Some(MetaItemKind::Word) => {
                 err(attr.span, "expected one argument");
diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs
index be00c57..1d3ace9 100644
--- a/src/librustc_typeck/expr_use_visitor.rs
+++ b/src/librustc_typeck/expr_use_visitor.rs
@@ -3,7 +3,6 @@
 //! `ExprUseVisitor` determines how expressions are being used.
 
 pub use self::ConsumeMode::*;
-use self::OverloadedCallType::*;
 
 // Export these here so that Clippy can use them.
 pub use mc::{Place, PlaceBase, Projection};
@@ -48,35 +47,6 @@
     WriteAndRead, // x += y
 }
 
-#[derive(Copy, Clone)]
-enum OverloadedCallType {
-    FnOverloadedCall,
-    FnMutOverloadedCall,
-    FnOnceOverloadedCall,
-}
-
-impl OverloadedCallType {
-    fn from_trait_id(tcx: TyCtxt<'_>, trait_id: DefId) -> OverloadedCallType {
-        for &(maybe_function_trait, overloaded_call_type) in &[
-            (tcx.lang_items().fn_once_trait(), FnOnceOverloadedCall),
-            (tcx.lang_items().fn_mut_trait(), FnMutOverloadedCall),
-            (tcx.lang_items().fn_trait(), FnOverloadedCall),
-        ] {
-            match maybe_function_trait {
-                Some(function_trait) if function_trait == trait_id => return overloaded_call_type,
-                _ => continue,
-            }
-        }
-
-        bug!("overloaded call didn't map to known function trait")
-    }
-
-    fn from_method_id(tcx: TyCtxt<'_>, method_id: DefId) -> OverloadedCallType {
-        let method = tcx.associated_item(method_id);
-        OverloadedCallType::from_trait_id(tcx, method.container.id())
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // The ExprUseVisitor type
 //
@@ -211,7 +181,7 @@
 
             hir::ExprKind::Call(ref callee, ref args) => {
                 // callee(args)
-                self.walk_callee(expr, callee);
+                self.consume_expr(callee);
                 self.consume_exprs(args);
             }
 
@@ -326,34 +296,6 @@
         }
     }
 
-    fn walk_callee(&mut self, call: &hir::Expr<'_>, callee: &hir::Expr<'_>) {
-        let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee));
-        debug!("walk_callee: callee={:?} callee_ty={:?}", callee, callee_ty);
-        match callee_ty.kind {
-            ty::FnDef(..) | ty::FnPtr(_) => {
-                self.consume_expr(callee);
-            }
-            ty::Error => {}
-            _ => {
-                if let Some(def_id) = self.mc.tables.type_dependent_def_id(call.hir_id) {
-                    match OverloadedCallType::from_method_id(self.tcx(), def_id) {
-                        FnMutOverloadedCall => {
-                            self.borrow_expr(callee, ty::MutBorrow);
-                        }
-                        FnOverloadedCall => {
-                            self.borrow_expr(callee, ty::ImmBorrow);
-                        }
-                        FnOnceOverloadedCall => self.consume_expr(callee),
-                    }
-                } else {
-                    self.tcx()
-                        .sess
-                        .delay_span_bug(call.span, "no type-dependent def for overloaded call");
-                }
-            }
-        }
-    }
-
     fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) {
         match stmt.kind {
             hir::StmtKind::Local(ref local) => {
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index b22d7c6..e9c18b5 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -12,6 +12,7 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -19,8 +20,6 @@
 
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 /// Checks that all the type/lifetime parameters on an impl also
 /// appear in the trait ref or self type (or are constrained by a
 /// where-clause). These rules are needed to ensure that, given a
@@ -74,10 +73,10 @@
 
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.kind {
+        if let hir::ItemKind::Impl { ref items, .. } = item.kind {
             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
-            enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_item_refs);
-            enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
+            enforce_impl_params_are_constrained(self.tcx, impl_def_id, items);
+            enforce_impl_items_are_distinct(self.tcx, items);
         }
     }
 
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8fba65d..3d27f91 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -64,15 +64,13 @@
 #![feature(exhaustive_patterns)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
 
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate syntax;
 
 #[macro_use]
 extern crate rustc;
@@ -104,14 +102,13 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util;
 use rustc::util::common::ErrorReported;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 
-use rustc_error_codes::*;
-
 use std::iter;
 
 use astconv::{AstConv, Bounds};
@@ -310,7 +307,7 @@
     // have valid types and not error
     // FIXME(matthewjasper) We shouldn't need to do this.
     tcx.sess.track_errors(|| {
-        tcx.sess.time("type collecting", || {
+        tcx.sess.time("type_collecting", || {
             for &module in tcx.hir().krate().modules.keys() {
                 tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
             }
@@ -319,35 +316,35 @@
 
     if tcx.features().rustc_attrs {
         tcx.sess.track_errors(|| {
-            tcx.sess.time("outlives testing", || outlives::test::test_inferred_outlives(tcx));
+            tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
         })?;
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("impl wf inference", || impl_wf_check::impl_wf_check(tcx));
+        tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
     })?;
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("coherence checking", || coherence::check_coherence(tcx));
+        tcx.sess.time("coherence_checking", || coherence::check_coherence(tcx));
     })?;
 
     if tcx.features().rustc_attrs {
         tcx.sess.track_errors(|| {
-            tcx.sess.time("variance testing", || variance::test::test_variance(tcx));
+            tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
         })?;
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("wf checking", || check::check_wf_new(tcx));
+        tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
     })?;
 
-    tcx.sess.time("item-types checking", || {
+    tcx.sess.time("item_types_checking", || {
         for &module in tcx.hir().krate().modules.keys() {
             tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
         }
     });
 
-    tcx.sess.time("item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
+    tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
 
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
@@ -383,6 +380,7 @@
         &item_cx,
         hir_trait,
         DUMMY_SP,
+        syntax::ast::Constness::NotConst,
         tcx.types.err,
         &mut bounds,
         true,
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index f8907c8..980d58a 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -1,10 +1,9 @@
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 
-use rustc_error_codes::*;
-
 pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
     tcx.hir().krate().visit_all_item_likes(&mut OutlivesTest { tcx });
 }
@@ -21,7 +20,7 @@
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, sym::rustc_outlives) {
             let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
-            span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of);
+            struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit();
         }
     }
 
diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs
index 251732b..99b7b20 100644
--- a/src/librustc_typeck/structured_errors.rs
+++ b/src/librustc_typeck/structured_errors.rs
@@ -1,10 +1,8 @@
-use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::session::Session;
 use rustc::ty::{Ty, TypeFoldable};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
@@ -50,8 +48,7 @@
     }
 
     fn code(&self) -> DiagnosticId {
-        syntax::diagnostic_used!(E0617);
-        DiagnosticId::Error("E0617".to_owned())
+        rustc_errors::error_code!(E0617)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
@@ -112,8 +109,7 @@
     }
 
     fn code(&self) -> DiagnosticId {
-        syntax::diagnostic_used!(E0607);
-        DiagnosticId::Error("E0607".to_owned())
+        rustc_errors::error_code!(E0607)
     }
 
     fn common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs
index a8003a5..ee94b10 100644
--- a/src/librustc_typeck/variance/test.rs
+++ b/src/librustc_typeck/variance/test.rs
@@ -1,10 +1,9 @@
 use rustc::ty::TyCtxt;
+use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 
-use rustc_error_codes::*;
-
 pub fn test_variance(tcx: TyCtxt<'_>) {
     tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx });
 }
@@ -21,7 +20,7 @@
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, sym::rustc_variance) {
             let variances_of = self.tcx.variances_of(item_def_id);
-            span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of);
+            struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit();
         }
     }
 
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index c8b63ed..27f8059 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -239,7 +239,7 @@
         //  constraint, and add it to our list. Since we make sure to never re-add
         //  deleted items, this process will always finish.
         while !vid_map.is_empty() {
-            let target = vid_map.keys().next().expect("Keys somehow empty").clone();
+            let target = *vid_map.keys().next().expect("Keys somehow empty");
             let deps = vid_map.remove(&target).expect("Entry somehow missing");
 
             for smaller in deps.smaller.iter() {
@@ -462,7 +462,7 @@
             .filter(|p| {
                 !orig_bounds.contains(p)
                     || match p {
-                        &&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait,
+                        ty::Predicate::Trait(pred, _) => pred.def_id() == sized_trait,
                         _ => false,
                     }
             })
@@ -560,8 +560,8 @@
                     lifetime_to_bounds.entry(lifetime).or_default().extend(bounds);
                 }
                 WherePredicate::EqPredicate { lhs, rhs } => {
-                    match &lhs {
-                        &Type::QPath { name: ref left_name, ref self_type, ref trait_ } => {
+                    match lhs {
+                        Type::QPath { name: ref left_name, ref self_type, ref trait_ } => {
                             let ty = &*self_type;
                             match **trait_ {
                                 Type::ResolvedPath {
@@ -580,36 +580,30 @@
                                         continue;
                                     }
 
-                                    // FIXME: Remove this scope when NLL lands
-                                    {
-                                        let args = &mut new_trait_path
-                                            .segments
-                                            .last_mut()
-                                            .expect("segments were empty")
-                                            .args;
+                                    let args = &mut new_trait_path
+                                        .segments
+                                        .last_mut()
+                                        .expect("segments were empty")
+                                        .args;
 
-                                        match args {
-                                            // Convert somethiung like '<T as Iterator::Item> = u8'
-                                            // to 'T: Iterator<Item=u8>'
-                                            &mut GenericArgs::AngleBracketed {
-                                                ref mut bindings,
-                                                ..
-                                            } => {
-                                                bindings.push(TypeBinding {
-                                                    name: left_name.clone(),
-                                                    kind: TypeBindingKind::Equality { ty: rhs },
-                                                });
-                                            }
-                                            &mut GenericArgs::Parenthesized { .. } => {
-                                                existing_predicates.push(
-                                                    WherePredicate::EqPredicate {
-                                                        lhs: lhs.clone(),
-                                                        rhs,
-                                                    },
-                                                );
-                                                continue; // If something other than a Fn ends up
-                                                // with parenthesis, leave it alone
-                                            }
+                                    match args {
+                                        // Convert somethiung like '<T as Iterator::Item> = u8'
+                                        // to 'T: Iterator<Item=u8>'
+                                        GenericArgs::AngleBracketed {
+                                            ref mut bindings, ..
+                                        } => {
+                                            bindings.push(TypeBinding {
+                                                name: left_name.clone(),
+                                                kind: TypeBindingKind::Equality { ty: rhs },
+                                            });
+                                        }
+                                        GenericArgs::Parenthesized { .. } => {
+                                            existing_predicates.push(WherePredicate::EqPredicate {
+                                                lhs: lhs.clone(),
+                                                rhs,
+                                            });
+                                            continue; // If something other than a Fn ends up
+                                            // with parenthesis, leave it alone
                                         }
                                     }
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 525b1b2..18ebd25 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -1,7 +1,7 @@
 use rustc::infer::InferOk;
 use rustc::traits;
 use rustc::ty::subst::Subst;
-use rustc::ty::ToPredicate;
+use rustc::ty::{ToPredicate, WithConstness};
 use rustc_hir as hir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_span::DUMMY_SP;
@@ -64,7 +64,7 @@
                         match infcx.evaluate_obligation(&traits::Obligation::new(
                             cause,
                             param_env,
-                            trait_ref.to_predicate(),
+                            trait_ref.without_const().to_predicate(),
                         )) {
                             Ok(eval_result) => eval_result.may_apply(),
                             Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 13df189..84e6ff6 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -202,23 +202,34 @@
 
 impl ops::BitAndAssign for Cfg {
     fn bitand_assign(&mut self, other: Cfg) {
-        if *self == other {
-            return;
-        }
         match (self, other) {
             (&mut Cfg::False, _) | (_, Cfg::True) => {}
             (s, Cfg::False) => *s = Cfg::False,
             (s @ &mut Cfg::True, b) => *s = b,
-            (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => a.append(b),
-            (&mut Cfg::All(ref mut a), ref mut b) => a.push(mem::replace(b, Cfg::True)),
+            (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => {
+                for c in b.drain(..) {
+                    if !a.contains(&c) {
+                        a.push(c);
+                    }
+                }
+            }
+            (&mut Cfg::All(ref mut a), ref mut b) => {
+                if !a.contains(b) {
+                    a.push(mem::replace(b, Cfg::True));
+                }
+            }
             (s, Cfg::All(mut a)) => {
                 let b = mem::replace(s, Cfg::True);
-                a.push(b);
+                if !a.contains(&b) {
+                    a.push(b);
+                }
                 *s = Cfg::All(a);
             }
             (s, b) => {
-                let a = mem::replace(s, Cfg::True);
-                *s = Cfg::All(vec![a, b]);
+                if *s != b {
+                    let a = mem::replace(s, Cfg::True);
+                    *s = Cfg::All(vec![a, b]);
+                }
             }
         }
     }
@@ -234,23 +245,34 @@
 
 impl ops::BitOrAssign for Cfg {
     fn bitor_assign(&mut self, other: Cfg) {
-        if *self == other {
-            return;
-        }
         match (self, other) {
             (&mut Cfg::True, _) | (_, Cfg::False) => {}
             (s, Cfg::True) => *s = Cfg::True,
             (s @ &mut Cfg::False, b) => *s = b,
-            (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => a.append(b),
-            (&mut Cfg::Any(ref mut a), ref mut b) => a.push(mem::replace(b, Cfg::True)),
+            (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => {
+                for c in b.drain(..) {
+                    if !a.contains(&c) {
+                        a.push(c);
+                    }
+                }
+            }
+            (&mut Cfg::Any(ref mut a), ref mut b) => {
+                if !a.contains(b) {
+                    a.push(mem::replace(b, Cfg::True));
+                }
+            }
             (s, Cfg::Any(mut a)) => {
                 let b = mem::replace(s, Cfg::True);
-                a.push(b);
+                if !a.contains(&b) {
+                    a.push(b);
+                }
                 *s = Cfg::Any(a);
             }
             (s, b) => {
-                let a = mem::replace(s, Cfg::True);
-                *s = Cfg::Any(vec![a, b]);
+                if *s != b {
+                    let a = mem::replace(s, Cfg::True);
+                    *s = Cfg::Any(vec![a, b]);
+                }
             }
         }
     }
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 309f720..d090bf3 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -87,6 +87,12 @@
         x &= word_cfg("test3");
         assert_eq!(x, word_cfg("test3"));
 
+        x &= word_cfg("test3");
+        assert_eq!(x, word_cfg("test3"));
+
+        x &= word_cfg("test4");
+        assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
+
         x &= word_cfg("test4");
         assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
 
@@ -105,6 +111,18 @@
             ])
         );
 
+        x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]);
+        assert_eq!(
+            x,
+            Cfg::All(vec![
+                word_cfg("test3"),
+                word_cfg("test4"),
+                word_cfg("test5"),
+                word_cfg("test6"),
+                word_cfg("test7"),
+            ])
+        );
+
         let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]);
         y &= x;
         assert_eq!(
@@ -119,6 +137,14 @@
             ])
         );
 
+        let mut z = word_cfg("test8");
+        z &= Cfg::All(vec![word_cfg("test9"), word_cfg("test10")]);
+        assert_eq!(z, Cfg::All(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
+
+        let mut z = word_cfg("test11");
+        z &= Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]);
+        assert_eq!(z, Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]));
+
         assert_eq!(
             word_cfg("a") & word_cfg("b") & word_cfg("c"),
             Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
@@ -145,6 +171,12 @@
         x |= word_cfg("test3");
         assert_eq!(x, word_cfg("test3"));
 
+        x |= word_cfg("test3");
+        assert_eq!(x, word_cfg("test3"));
+
+        x |= word_cfg("test4");
+        assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
+
         x |= word_cfg("test4");
         assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
 
@@ -163,6 +195,18 @@
             ])
         );
 
+        x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]);
+        assert_eq!(
+            x,
+            Cfg::Any(vec![
+                word_cfg("test3"),
+                word_cfg("test4"),
+                word_cfg("test5"),
+                word_cfg("test6"),
+                word_cfg("test7"),
+            ])
+        );
+
         let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]);
         y |= x;
         assert_eq!(
@@ -177,6 +221,14 @@
             ])
         );
 
+        let mut z = word_cfg("test8");
+        z |= Cfg::Any(vec![word_cfg("test9"), word_cfg("test10")]);
+        assert_eq!(z, Cfg::Any(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
+
+        let mut z = word_cfg("test11");
+        z |= Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]);
+        assert_eq!(z, Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]));
+
         assert_eq!(
             word_cfg("a") | word_cfg("b") | word_cfg("c"),
             Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 2400dde..8a6abe0 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -9,6 +9,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
 use rustc_metadata::creader::LoadedMacro;
+use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -212,7 +213,7 @@
     let sig = cx.tcx.fn_sig(did);
 
     let constness =
-        if cx.tcx.is_min_const_fn(did) { hir::Constness::Const } else { hir::Constness::NotConst };
+        if is_min_const_fn(cx.tcx, did) { hir::Constness::Const } else { hir::Constness::NotConst };
     let asyncness = cx.tcx.asyncness(did);
     let predicates = cx.tcx.predicates_of(did);
     let (generics, decl) = clean::enter_impl_trait(cx, || {
@@ -272,6 +273,22 @@
     clean::Typedef {
         type_: cx.tcx.type_of(did).clean(cx),
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
+        item_type: build_type_alias_type(cx, did),
+    }
+}
+
+fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
+    let type_ = cx.tcx.type_of(did).clean(cx);
+    type_.def_id().and_then(|did| build_ty(cx, did))
+}
+
+pub fn build_ty(cx: &DocContext, did: DefId) -> Option<clean::Type> {
+    match cx.tcx.def_kind(did)? {
+        DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => {
+            Some(cx.tcx.type_of(did).clean(cx))
+        }
+        DefKind::TyAlias => build_type_alias_type(cx, did),
+        _ => None,
     }
 }
 
@@ -330,7 +347,7 @@
 
     let for_ = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
         match tcx.hir().expect_item(hir_id).kind {
-            hir::ItemKind::Impl(.., ref t, _) => t.clean(cx),
+            hir::ItemKind::Impl { self_ty, .. } => self_ty.clean(cx),
             _ => panic!("did given to build_impl was not an impl"),
         }
     } else {
@@ -350,9 +367,9 @@
     let predicates = tcx.explicit_predicates_of(did);
     let (trait_items, generics) = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
         match tcx.hir().expect_item(hir_id).kind {
-            hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => (
-                item_ids.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>(),
-                gen.clean(cx),
+            hir::ItemKind::Impl { ref generics, ref items, .. } => (
+                items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
+                generics.clean(cx),
             ),
             _ => panic!("did given to build_impl was not an impl"),
         }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index bb46a15..7a7d69c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -21,6 +21,7 @@
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{self, Pos};
@@ -481,7 +482,7 @@
         use rustc::ty::Predicate;
 
         match *self {
-            Predicate::Trait(ref pred) => Some(pred.clean(cx)),
+            Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
             Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
@@ -895,7 +896,7 @@
             enter_impl_trait(cx, || (self.generics.clean(cx), (self.decl, self.body).clean(cx)));
 
         let did = cx.tcx.hir().local_def_id(self.id);
-        let constness = if cx.tcx.is_min_const_fn(did) {
+        let constness = if is_min_const_fn(cx.tcx, did) {
             hir::Constness::Const
         } else {
             hir::Constness::NotConst
@@ -1121,7 +1122,9 @@
                 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
             }
             hir::ImplItemKind::TyAlias(ref ty) => {
-                TypedefItem(Typedef { type_: ty.clean(cx), generics: Generics::default() }, true)
+                let type_ = ty.clean(cx);
+                let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
+                TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
             }
             hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
                 OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
@@ -1187,7 +1190,7 @@
                 };
                 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
                 if provided {
-                    let constness = if cx.tcx.is_min_const_fn(self.def_id) {
+                    let constness = if is_min_const_fn(cx.tcx, self.def_id) {
                         hir::Constness::Const
                     } else {
                         hir::Constness::NotConst
@@ -1281,10 +1284,13 @@
 
                     AssocTypeItem(bounds, ty.clean(cx))
                 } else {
+                    let type_ = cx.tcx.type_of(self.def_id).clean(cx);
+                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
                     TypedefItem(
                         Typedef {
-                            type_: cx.tcx.type_of(self.def_id).clean(cx),
+                            type_,
                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
+                            item_type,
                         },
                         true,
                     )
@@ -1988,6 +1994,8 @@
 
 impl Clean<Item> for doctree::Typedef<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
+        let type_ = self.ty.clean(cx);
+        let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -1996,10 +2004,7 @@
             visibility: self.vis.clean(cx),
             stability: cx.stability(self.id).clean(cx),
             deprecation: cx.deprecation(self.id).clean(cx),
-            inner: TypedefItem(
-                Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) },
-                false,
-            ),
+            inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
         }
     }
 }
@@ -2100,7 +2105,7 @@
             build_deref_target_impls(cx, &items, &mut ret);
         }
 
-        let provided = trait_
+        let provided: FxHashSet<String> = trait_
             .def_id()
             .map(|did| {
                 cx.tcx
@@ -2111,7 +2116,12 @@
             })
             .unwrap_or_default();
 
-        ret.push(Item {
+        let for_ = self.for_.clean(cx);
+        let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
+            Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
+            _ => None,
+        });
+        let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
@@ -2122,15 +2132,19 @@
             inner: ImplItem(Impl {
                 unsafety: self.unsafety,
                 generics: self.generics.clean(cx),
-                provided_trait_methods: provided,
+                provided_trait_methods: provided.clone(),
                 trait_,
-                for_: self.for_.clean(cx),
+                for_,
                 items,
                 polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
                 synthetic: false,
                 blanket_impl: None,
             }),
-        });
+        };
+        if let Some(type_alias) = type_alias {
+            ret.push(make_item(trait_.clone(), type_alias, items.clone()));
+        }
+        ret.push(make_item(trait_, for_, items));
         ret
     }
 }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index c7b12d3..2b59c60 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -141,7 +141,7 @@
         .predicates
         .iter()
         .filter_map(|(pred, _)| {
-            if let ty::Predicate::Trait(ref pred) = *pred {
+            if let ty::Predicate::Trait(ref pred, _) = *pred {
                 if pred.skip_binder().trait_ref.self_ty() == self_ty {
                     Some(pred.def_id())
                 } else {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index c8f1dff..79a078c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -497,7 +497,7 @@
         false
     }
 
-    pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
+    pub fn from_ast(diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
         let mut doc_strings = vec![];
         let mut sp = None;
         let mut cfg = Cfg::True;
@@ -1406,6 +1406,14 @@
 pub struct Typedef {
     pub type_: Type,
     pub generics: Generics,
+    // Type of target item.
+    pub item_type: Option<Type>,
+}
+
+impl GetDefId for Typedef {
+    fn def_id(&self) -> Option<DefId> {
+        self.type_.def_id()
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 874cb9b..8058536 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -460,12 +460,16 @@
 
 pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
     match n.val {
-        ty::ConstKind::Unevaluated(def_id, _) => {
-            if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
+        ty::ConstKind::Unevaluated(def_id, _, promoted) => {
+            let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
                 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
                 inline::print_inlined_const(cx, def_id)
+            };
+            if let Some(promoted) = promoted {
+                s.push_str(&format!("::{:?}", promoted))
             }
+            s
         }
         _ => {
             let mut s = n.to_string();
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 0af25ef..22f5d0d 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -3,7 +3,6 @@
 use std::fmt;
 use std::path::PathBuf;
 
-use errors;
 use getopts;
 use rustc::lint::Level;
 use rustc::session;
@@ -24,7 +23,7 @@
 use crate::html::markdown::IdMap;
 use crate::html::static_files;
 use crate::opts;
-use crate::passes::{self, DefaultPassOption};
+use crate::passes::{self, Condition, DefaultPassOption};
 use crate::theme;
 
 /// Configuration options for rustdoc.
@@ -98,6 +97,10 @@
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
     pub default_passes: DefaultPassOption,
+    /// Document items that have lower than `pub` visibility.
+    pub document_private: bool,
+    /// Document items that have `doc(hidden)`.
+    pub document_hidden: bool,
     /// Any passes manually selected by the user.
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
@@ -146,6 +149,8 @@
             .field("test_args", &self.test_args)
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
+            .field("document_private", &self.document_private)
+            .field("document_hidden", &self.document_hidden)
             .field("manual_passes", &self.manual_passes)
             .field("display_warnings", &self.display_warnings)
             .field("show_coverage", &self.show_coverage)
@@ -240,22 +245,26 @@
                 println!("{:>20} - {}", pass.name, pass.description);
             }
             println!("\nDefault passes for rustdoc:");
-            for pass in passes::DEFAULT_PASSES {
-                println!("{:>20}", pass.name);
-            }
-            println!("\nPasses run with `--document-private-items`:");
-            for pass in passes::DEFAULT_PRIVATE_PASSES {
-                println!("{:>20}", pass.name);
+            for p in passes::DEFAULT_PASSES {
+                print!("{:>20}", p.pass.name);
+                println_condition(p.condition);
             }
 
             if nightly_options::is_nightly_build() {
                 println!("\nPasses run with `--show-coverage`:");
-                for pass in passes::DEFAULT_COVERAGE_PASSES {
-                    println!("{:>20}", pass.name);
+                for p in passes::COVERAGE_PASSES {
+                    print!("{:>20}", p.pass.name);
+                    println_condition(p.condition);
                 }
-                println!("\nPasses run with `--show-coverage --document-private-items`:");
-                for pass in passes::PRIVATE_COVERAGE_PASSES {
-                    println!("{:>20}", pass.name);
+            }
+
+            fn println_condition(condition: Condition) {
+                use Condition::*;
+                match condition {
+                    Always => println!(),
+                    WhenDocumentPrivate => println!("  (when --document-private-items)"),
+                    WhenNotDocumentPrivate => println!("  (when not --document-private-items)"),
+                    WhenNotDocumentHidden => println!("  (when not --document-hidden-items)"),
                 }
             }
 
@@ -444,16 +453,11 @@
             });
 
         let show_coverage = matches.opt_present("show-coverage");
-        let document_private = matches.opt_present("document-private-items");
 
         let default_passes = if matches.opt_present("no-defaults") {
             passes::DefaultPassOption::None
-        } else if show_coverage && document_private {
-            passes::DefaultPassOption::PrivateCoverage
         } else if show_coverage {
             passes::DefaultPassOption::Coverage
-        } else if document_private {
-            passes::DefaultPassOption::Private
         } else {
             passes::DefaultPassOption::Default
         };
@@ -492,6 +496,8 @@
         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 document_private = matches.opt_present("document-private-items");
+        let document_hidden = matches.opt_present("document-hidden-items");
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -518,6 +524,8 @@
             should_test,
             test_args,
             default_passes,
+            document_private,
+            document_hidden,
             manual_passes,
             display_warnings,
             show_coverage,
@@ -557,7 +565,7 @@
 }
 
 /// Prints deprecation warnings for deprecated options
-fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) {
+fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Handler) {
     let deprecated_flags = ["input-format", "output-format", "no-defaults", "passes"];
 
     for flag in deprecated_flags.iter() {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 50d6202..4c8b811 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -1,4 +1,3 @@
-use rustc::lint;
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
 use rustc::session::config::ErrorOutputType;
@@ -14,9 +13,10 @@
 use rustc_interface::interface;
 use rustc_lint;
 use rustc_resolve as resolve;
+use rustc_session::lint;
 
-use errors::emitter::{Emitter, EmitterWriter};
-use errors::json::JsonEmitter;
+use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::json::JsonEmitter;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
@@ -33,7 +33,7 @@
 use crate::config::{Options as RustdocOptions, RenderOptions};
 use crate::html::render::RenderInfo;
 
-use crate::passes;
+use crate::passes::{self, Condition::*, ConditionalPass};
 
 pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options};
 pub use rustc::session::search_paths::SearchPath;
@@ -171,7 +171,7 @@
     error_format: ErrorOutputType,
     source_map: Option<Lrc<source_map::SourceMap>>,
     debugging_opts: &DebuggingOptions,
-) -> errors::Handler {
+) -> rustc_errors::Handler {
     let emitter: Box<dyn Emitter + sync::Send> = match error_format {
         ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -198,7 +198,10 @@
         }
     };
 
-    errors::Handler::with_emitter_and_flags(emitter, debugging_opts.diagnostic_handler_flags(true))
+    rustc_errors::Handler::with_emitter_and_flags(
+        emitter,
+        debugging_opts.diagnostic_handler_flags(true),
+    )
 }
 
 pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) {
@@ -221,6 +224,8 @@
         describe_lints,
         lint_cap,
         mut default_passes,
+        mut document_private,
+        document_hidden,
         mut manual_passes,
         display_warnings,
         render_options,
@@ -302,8 +307,7 @@
         cg: codegen_options,
         externs,
         target_triple: target,
-        // Ensure that rustdoc works even if rustc is feature-staged
-        unstable_features: UnstableFeatures::Allow,
+        unstable_features: UnstableFeatures::from_environment(),
         actually_rustdoc: true,
         debugging_opts: debugging_options,
         error_format,
@@ -407,7 +411,7 @@
 
                 let mut krate = clean::krate(&mut ctxt);
 
-                fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
+                fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) {
                     let mut msg = diag.struct_warn(&format!(
                         "the `#![doc({})]` attribute is \
                                                          considered deprecated",
@@ -457,16 +461,14 @@
                     }
 
                     if attr.is_word() && name == sym::document_private_items {
-                        if default_passes == passes::DefaultPassOption::Default {
-                            default_passes = passes::DefaultPassOption::Private;
-                        }
+                        document_private = true;
                     }
                 }
 
-                let passes = passes::defaults(default_passes).iter().chain(
+                let passes = passes::defaults(default_passes).iter().copied().chain(
                     manual_passes.into_iter().flat_map(|name| {
                         if let Some(pass) = passes::find_pass(&name) {
-                            Some(pass)
+                            Some(ConditionalPass::always(pass))
                         } else {
                             error!("unknown pass {}, skipping", name);
                             None
@@ -476,9 +478,17 @@
 
                 info!("Executing passes");
 
-                for pass in passes {
-                    debug!("running pass {}", pass.name);
-                    krate = (pass.pass)(krate, &ctxt);
+                for p in passes {
+                    let run = match p.condition {
+                        Always => true,
+                        WhenDocumentPrivate => document_private,
+                        WhenNotDocumentPrivate => !document_private,
+                        WhenNotDocumentHidden => !document_hidden,
+                    };
+                    if run {
+                        debug!("running pass {}", p.pass.name);
+                        krate = (p.pass.run)(krate, &ctxt);
+                    }
                 }
 
                 ctxt.sess().abort_if_errors();
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 2a107e8..ecc394a 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -9,8 +9,6 @@
 //! needs to read-after-write from a file, then it would be added to this
 //! abstraction.
 
-use errors;
-
 use std::fs;
 use std::io;
 use std::path::Path;
@@ -42,7 +40,7 @@
     }
 
     /// Prints all stored errors. Returns the number of printed errors.
-    pub fn write_errors(&mut self, diag: &errors::Handler) -> usize {
+    pub fn write_errors(&mut self, diag: &rustc_errors::Handler) -> usize {
         let mut printed = 0;
         // In order to drop the sender part of the channel.
         self.sender = None;
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 178ba69..218674b 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -203,6 +203,7 @@
     pub unsafety: hir::Unsafety,
     pub polarity: hir::ImplPolarity,
     pub defaultness: hir::Defaultness,
+    pub constness: ast::Constness,
     pub generics: &'hir hir::Generics<'hir>,
     pub trait_: &'hir Option<hir::TraitRef<'hir>>,
     pub for_: &'hir hir::Ty<'hir>,
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index e0ed02c..8b5a3a2 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -1,6 +1,5 @@
 use crate::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};
 use crate::rustc_span::edition::Edition;
-use errors;
 use rustc_feature::UnstableFeatures;
 use std::fs;
 use std::path::Path;
@@ -26,7 +25,7 @@
         after_content: &[String],
         md_before_content: &[String],
         md_after_content: &[String],
-        diag: &errors::Handler,
+        diag: &rustc_errors::Handler,
         id_map: &mut IdMap,
         edition: Edition,
         playground: &Option<Playground>,
@@ -58,7 +57,7 @@
 
 pub fn load_string<P: AsRef<Path>>(
     file_path: P,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
 ) -> Result<String, LoadStringError> {
     let file_path = file_path.as_ref();
     let contents = match fs::read(file_path) {
@@ -77,7 +76,7 @@
     }
 }
 
-fn load_external_files(names: &[String], diag: &errors::Handler) -> Option<String> {
+fn load_external_files(names: &[String], diag: &rustc_errors::Handler) -> Option<String> {
     let mut out = String::new();
     for name in names {
         let s = match load_string(name, diag) {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 6434dcc..79923fc 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -361,6 +361,7 @@
                 let modifier_str = match modifier {
                     hir::TraitBoundModifier::None => "",
                     hir::TraitBoundModifier::Maybe => "?",
+                    hir::TraitBoundModifier::MaybeConst => "?const",
                 };
                 if f.alternate() {
                     write!(f, "{}{:#}", modifier_str, ty.print())
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index fb6bdcd..5bea1b5 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -41,7 +41,7 @@
     let fm = sess
         .source_map()
         .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned());
-    let highlight_result = {
+    let highlight_result = rustc_driver::catch_fatal_errors(|| {
         let lexer = lexer::StringReader::new(&sess, fm, None);
         let mut classifier = Classifier::new(lexer, sess.source_map());
 
@@ -51,7 +51,8 @@
         } else {
             Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
         }
-    };
+    })
+    .unwrap_or(Err(()));
 
     match highlight_result {
         Ok(highlighted_source) => {
@@ -65,7 +66,7 @@
         Err(()) => {
             // If errors are encountered while trying to highlight, just emit
             // the unhighlighted source.
-            write!(out, "<pre><code>{}</code></pre>", src).unwrap();
+            write!(out, "<pre><code>{}</code></pre>", Escape(src)).unwrap();
         }
     }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index c5f88f9..c87964a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -380,7 +380,10 @@
                     }
                     _ => {}
                 }
-                self.buf.push_back(event);
+                match event {
+                    Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
+                    event => self.buf.push_back(event),
+                }
             }
             let id = self.id_map.derive(id);
 
@@ -395,7 +398,7 @@
 
             let start_tags = format!(
                 "<h{level} id=\"{id}\" class=\"section-header\">\
-                                      <a href=\"#{id}\">",
+                    <a href=\"#{id}\">",
                 id = id,
                 level = level
             );
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index a01e2f7..c73960f 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -42,7 +42,6 @@
 use std::str;
 use std::sync::Arc;
 
-use errors;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
 use rustc_data_structures::flock;
@@ -394,7 +393,7 @@
     mut krate: clean::Crate,
     options: RenderOptions,
     renderinfo: RenderInfo,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
     edition: Edition,
 ) -> Result<(), Error> {
     // need to save a copy of the options for rendering the index page
@@ -528,7 +527,7 @@
     krate: &clean::Crate,
     search_index: String,
     options: &RenderOptions,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
 ) -> Result<(), Error> {
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
@@ -993,13 +992,11 @@
             writeln!(v, "{}", *implementor).unwrap();
         }
         v.push_str(
-            r"
-            if (window.register_implementors) {
-                window.register_implementors(implementors);
-            } else {
-                window.pending_implementors = implementors;
-            }
-        ",
+            "if (window.register_implementors) {\
+                 window.register_implementors(implementors);\
+             } else {\
+                 window.pending_implementors = implementors;\
+             }",
         );
         v.push_str("})()");
         cx.shared.fs.write(&mydst, &v)?;
@@ -2322,8 +2319,8 @@
         "{}{}{}{}{:#}fn {}{:#}",
         it.visibility.print_with_space(),
         f.header.constness.print_with_space(),
-        f.header.unsafety.print_with_space(),
         f.header.asyncness.print_with_space(),
+        f.header.unsafety.print_with_space(),
         print_abi_with_space(f.header.abi),
         it.name.as_ref().unwrap(),
         f.generics.print()
@@ -2333,12 +2330,12 @@
     render_attributes(w, it, false);
     write!(
         w,
-        "{vis}{constness}{unsafety}{asyncness}{abi}fn \
+        "{vis}{constness}{asyncness}{unsafety}{abi}fn \
            {name}{generics}{decl}{where_clause}</pre>",
         vis = it.visibility.print_with_space(),
         constness = f.header.constness.print_with_space(),
-        unsafety = f.header.unsafety.print_with_space(),
         asyncness = f.header.asyncness.print_with_space(),
+        unsafety = f.header.unsafety.print_with_space(),
         abi = print_abi_with_space(f.header.abi),
         name = it.name.as_ref().unwrap(),
         generics = f.generics.print(),
@@ -2354,6 +2351,7 @@
     implementor: &Impl,
     w: &mut Buffer,
     implementor_dups: &FxHashMap<&str, (DefId, bool)>,
+    aliases: &[String],
 ) {
     // If there's already another implementor that has the same abbridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
@@ -2376,6 +2374,7 @@
         Some(use_absolute),
         false,
         false,
+        aliases,
     );
 }
 
@@ -2397,6 +2396,7 @@
                 None,
                 false,
                 true,
+                &[],
             );
             buffer.into_inner()
         })
@@ -2598,8 +2598,6 @@
     // If there are methods directly on this trait object, render them here.
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All);
 
-    let mut synthetic_types = Vec::new();
-
     if let Some(implementors) = cx.cache.implementors.get(&it.def_id) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
@@ -2650,6 +2648,7 @@
                     None,
                     true,
                     false,
+                    &[],
                 );
             }
             write_loading_content(w, "");
@@ -2662,7 +2661,7 @@
             "<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>");
 
@@ -2674,9 +2673,13 @@
                 "<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,
+                    &collect_paths_for_type(implementor.inner_impl().for_.clone()),
+                );
             }
             write_loading_content(w, "</div>");
         }
@@ -2701,17 +2704,12 @@
             write_loading_content(w, "</div>");
         }
     }
-    write!(
-        w,
-        r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
-        serde_json::to_string(&synthetic_types).unwrap(),
-    );
 
     write!(
         w,
-        r#"<script type="text/javascript" async
-                         src="{root_path}/implementors/{path}/{ty}.{name}.js">
-                 </script>"#,
+        "<script type=\"text/javascript\" \
+                 src=\"{root_path}/implementors/{path}/{ty}.{name}.js\" async>\
+         </script>",
         root_path = vec![".."; cx.current.len()].join("/"),
         path = if it.def_id.is_local() {
             cx.current.join("/")
@@ -2833,8 +2831,8 @@
             "{}{}{}{}{}{:#}fn {}{:#}",
             meth.visibility.print_with_space(),
             header.constness.print_with_space(),
-            header.unsafety.print_with_space(),
             header.asyncness.print_with_space(),
+            header.unsafety.print_with_space(),
             print_default_space(meth.is_default()),
             print_abi_with_space(header.abi),
             name,
@@ -2855,8 +2853,8 @@
             if parent == ItemType::Trait { "    " } else { "" },
             meth.visibility.print_with_space(),
             header.constness.print_with_space(),
-            header.unsafety.print_with_space(),
             header.asyncness.print_with_space(),
+            header.unsafety.print_with_space(),
             print_default_space(meth.is_default()),
             print_abi_with_space(header.abi),
             href = href,
@@ -3393,6 +3391,7 @@
                 None,
                 false,
                 true,
+                &[],
             );
         }
     }
@@ -3470,20 +3469,23 @@
     deref_mut: bool,
 ) {
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
-    let target = impl_
+    let (target, real_target) = impl_
         .inner_impl()
         .items
         .iter()
         .filter_map(|item| match item.inner {
-            clean::TypedefItem(ref t, true) => Some(&t.type_),
+            clean::TypedefItem(ref t, true) => Some(match *t {
+                clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
+                _ => (&t.type_, &t.type_),
+            }),
             _ => None,
         })
         .next()
         .expect("Expected associated type binding");
     let what =
-        AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut };
+        AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
     if let Some(did) = target.def_id() {
-        render_assoc_items(w, cx, container_item, did, what)
+        render_assoc_items(w, cx, container_item, did, what);
     } else {
         if let Some(prim) = target.primitive_type() {
             if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
@@ -3600,6 +3602,9 @@
     use_absolute: Option<bool>,
     is_on_foreign_type: bool,
     show_default_items: bool,
+    // This argument is used to reference same type with different pathes to avoid duplication
+    // in documentation pages for trait with automatic implementations like "Send" and "Sync".
+    aliases: &[String],
 ) {
     if render_mode == RenderMode::Normal {
         let id = cx.derive_id(match i.inner_impl().trait_ {
@@ -3612,8 +3617,13 @@
             }
             None => "impl".to_string(),
         });
+        let aliases = if aliases.is_empty() {
+            String::new()
+        } else {
+            format!(" aliases=\"{}\"", aliases.join(","))
+        };
         if let Some(use_absolute) = use_absolute {
-            write!(w, "<h3 id='{}' class='impl'><code class='in-band'>", id);
+            write!(w, "<h3 id='{}' class='impl'{}><code class='in-band'>", id, aliases);
             fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute);
             if show_def_docs {
                 for it in &i.inner_impl().items {
@@ -3635,8 +3645,9 @@
         } else {
             write!(
                 w,
-                "<h3 id='{}' class='impl'><code class='in-band'>{}</code>",
+                "<h3 id='{}' class='impl'{}><code class='in-band'>{}</code>",
                 id,
+                aliases,
                 i.inner_impl().print()
             );
         }
@@ -4124,12 +4135,15 @@
                 .filter(|i| i.inner_impl().trait_.is_some())
                 .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
             {
-                if let Some(target) = impl_
+                if let Some((target, real_target)) = impl_
                     .inner_impl()
                     .items
                     .iter()
                     .filter_map(|item| match item.inner {
-                        clean::TypedefItem(ref t, true) => Some(&t.type_),
+                        clean::TypedefItem(ref t, true) => Some(match *t {
+                            clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
+                            _ => (&t.type_, &t.type_),
+                        }),
                         _ => None,
                     })
                     .next()
@@ -4148,7 +4162,7 @@
                                 "{:#}",
                                 impl_.inner_impl().trait_.as_ref().unwrap().print()
                             )),
-                            Escape(&format!("{:#}", target.print()))
+                            Escape(&format!("{:#}", real_target.print()))
                         ));
                         out.push_str("</a>");
                         let mut ret = impls
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 2250744..f1f83ac 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -277,7 +277,7 @@
                 | clean::StructFieldItem(..)
                 | clean::VariantItem(..) => (
                     (
-                        Some(*self.parent_stack.last().unwrap()),
+                        Some(*self.parent_stack.last().expect("parent_stack is empty")),
                         Some(&self.stack[..self.stack.len() - 1]),
                     ),
                     false,
@@ -286,7 +286,7 @@
                     if self.parent_stack.is_empty() {
                         ((None, None), false)
                     } else {
-                        let last = self.parent_stack.last().unwrap();
+                        let last = self.parent_stack.last().expect("parent_stack is empty 2");
                         let did = *last;
                         let path = match self.paths.get(&did) {
                             // The current stack not necessarily has correlation
@@ -468,7 +468,7 @@
                         self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
                     }
                 } else {
-                    let trait_did = impl_item.trait_did().unwrap();
+                    let trait_did = impl_item.trait_did().expect("no trait did");
                     self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
                 None
@@ -478,10 +478,10 @@
         });
 
         if pushed {
-            self.stack.pop().unwrap();
+            self.stack.pop().expect("stack already empty");
         }
         if parent_pushed {
-            self.parent_stack.pop().unwrap();
+            self.parent_stack.pop().expect("parent stack already empty");
         }
         self.stripped_mod = orig_stripped_mod;
         self.parent_is_trait_impl = orig_parent_is_trait_impl;
@@ -594,7 +594,7 @@
     for item in search_index {
         item.parent_idx = item.parent.map(|nodeid| {
             if nodeid_to_pathid.contains_key(&nodeid) {
-                *nodeid_to_pathid.get(&nodeid).unwrap()
+                *nodeid_to_pathid.get(&nodeid).expect("no pathid")
             } else {
                 let pathid = lastpathid;
                 nodeid_to_pathid.insert(nodeid, pathid);
@@ -639,7 +639,7 @@
             items: crate_items,
             paths: crate_paths,
         })
-        .unwrap()
+        .expect("failed serde conversion")
     )
 }
 
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 8ccb74d..ec881d2 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1895,6 +1895,22 @@
         var implementors = document.getElementById("implementors-list");
         var synthetic_implementors = document.getElementById("synthetic-implementors-list");
 
+        // This `inlined_types` variable is used to avoid having the same implementation showing
+        // up twice. For example "String" in the "Sync" doc page.
+        //
+        // By the way, this is only used by and useful for traits implemented automatically (like
+        // "Send" and "Sync").
+        var inlined_types = new Set();
+        onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
+            var aliases = el.getAttribute("aliases");
+            if (!aliases) {
+                return;
+            }
+            aliases.split(",").forEach(function(alias) {
+                inlined_types.add(alias);
+            });
+        });
+
         var libs = Object.getOwnPropertyNames(imp);
         var llength = libs.length;
         for (var i = 0; i < llength; ++i) {
@@ -1911,10 +1927,10 @@
                 if (struct.synthetic) {
                     var stlength = struct.types.length;
                     for (var k = 0; k < stlength; k++) {
-                        if (window.inlined_types.has(struct.types[k])) {
+                        if (inlined_types.has(struct.types[k])) {
                             continue struct_loop;
                         }
-                        window.inlined_types.add(struct.types[k]);
+                        inlined_types.add(struct.types[k]);
                     }
                 }
 
@@ -2663,8 +2679,8 @@
             "Accepted types are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
              <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
              and <code>const</code>.",
-            "Search functions by type signature (e.g., <code>vec -> usize</code> or \
-             <code>* -> vec</code>)",
+            "Search functions by type signature (e.g., <code>vec -&gt; usize</code> or \
+             <code>* -&gt; vec</code>)",
             "Search multiple things at once by splitting your query with comma (e.g., \
              <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
             "You can look for items with an exact name by putting double quotes around \
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 62fe230..a91fdb7 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -542,11 +542,11 @@
 }
 
 .content .stability::before {
-	content: '˪';
-	font-size: 30px;
+	content: '⬑';
+	font-size: 25px;
 	position: absolute;
-	top: -9px;
-	left: -13px;
+	top: -6px;
+	left: -19px;
 }
 
 .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index f46bd6d..9a0e7bb 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -105,6 +105,8 @@
 .content .highlighted.primitive { background-color: #00708a; }
 .content .highlighted.keyword { background-color: #884719; }
 
+.content .stability::before { color: #ccc; }
+
 .content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
 .content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index ca67b1c..ca8ea1c 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -105,6 +105,8 @@
 .content .highlighted.primitive { background-color: #9aecff; }
 .content .highlighted.keyword { background-color: #f99650; }
 
+.content .stability::before { color: #ccc; }
+
 .content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
 .content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index eeaac1d..403c8d0 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -10,9 +10,9 @@
 #![feature(nll)]
 #![feature(set_stdio)]
 #![feature(test)]
+#![feature(vec_remove_item)]
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
-#![feature(const_fn)]
 #![feature(drain_filter)]
 #![feature(never_type)]
 #![feature(unicode_internals)]
@@ -23,7 +23,7 @@
 extern crate rustc;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
-extern crate rustc_error_codes;
+extern crate rustc_errors;
 extern crate rustc_expand;
 extern crate rustc_feature;
 extern crate rustc_hir;
@@ -32,8 +32,10 @@
 extern crate rustc_lexer;
 extern crate rustc_lint;
 extern crate rustc_metadata;
+extern crate rustc_mir;
 extern crate rustc_parse;
 extern crate rustc_resolve;
+extern crate rustc_session;
 extern crate rustc_span as rustc_span;
 extern crate rustc_target;
 extern crate rustc_typeck;
@@ -41,7 +43,6 @@
 extern crate test as testing;
 #[macro_use]
 extern crate log;
-extern crate rustc_errors as errors;
 
 use std::default::Default;
 use std::env;
@@ -173,6 +174,9 @@
         stable("document-private-items", |o| {
             o.optflag("", "document-private-items", "document private items")
         }),
+        unstable("document-hidden-items", |o| {
+            o.optflag("", "document-hidden-items", "document items that have doc(hidden)")
+        }),
         stable("test", |o| o.optflag("", "test", "run code examples as tests")),
         stable("test-args", |o| {
             o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS")
@@ -514,6 +518,6 @@
 
     match result {
         Ok(output) => output,
-        Err(_) => panic::resume_unwind(Box::new(errors::FatalErrorMarker)),
+        Err(_) => panic::resume_unwind(Box::new(rustc_errors::FatalErrorMarker)),
     }
 }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 69aa248..912a407 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -2,7 +2,6 @@
 use std::io::prelude::*;
 use std::path::PathBuf;
 
-use errors;
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::DUMMY_SP;
@@ -39,7 +38,7 @@
 pub fn render(
     input: PathBuf,
     options: RenderOptions,
-    diag: &errors::Handler,
+    diag: &rustc_errors::Handler,
     edition: Edition,
 ) -> i32 {
     let mut output = options.output;
@@ -128,7 +127,7 @@
 }
 
 /// Runs any tests/code examples in the markdown file `input`.
-pub fn test(mut options: Options, diag: &errors::Handler) -> i32 {
+pub fn test(mut options: Options, diag: &rustc_errors::Handler) -> i32 {
     let input_str = match load_string(&options.input, diag) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 803bcc2..7ed531c 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -12,7 +12,7 @@
 
 pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
     name: "calculate-doc-coverage",
-    pass: calculate_doc_coverage,
+    run: calculate_doc_coverage,
     description: "counts the number of items with and without documentation",
 };
 
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index a4ca901..2903fd9 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -1,5 +1,5 @@
-use errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
 use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler};
 use rustc_parse::lexer::StringReader as Lexer;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::{FileName, InnerSpan};
@@ -14,7 +14,7 @@
 
 pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
     name: "check-code-block-syntax",
-    pass: check_code_block_syntax,
+    run: check_code_block_syntax,
     description: "validates syntax inside Rust code blocks",
 };
 
@@ -40,7 +40,7 @@
             dox[code_block.code].to_owned(),
         );
 
-        let validation_status = {
+        let validation_status = rustc_driver::catch_fatal_errors(|| {
             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
@@ -61,7 +61,8 @@
             } else {
                 None
             }
-        };
+        })
+        .unwrap_or(Some(CodeBlockInvalid::SyntaxError));
 
         if let Some(code_block_invalid) = validation_status {
             let mut diag = if let Some(sp) =
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
index c6b2288..c218559 100644
--- a/src/librustdoc/passes/collapse_docs.rs
+++ b/src/librustdoc/passes/collapse_docs.rs
@@ -8,7 +8,7 @@
 
 pub const COLLAPSE_DOCS: Pass = Pass {
     name: "collapse-docs",
-    pass: collapse_docs,
+    run: collapse_docs,
     description: "concatenates all document attributes into one document attribute",
 };
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 8a3966c..50d5f70 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,6 +1,6 @@
-use errors::Applicability;
 use rustc::lint;
 use rustc::ty;
+use rustc_errors::Applicability;
 use rustc_expand::base::SyntaxExtensionKind;
 use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
@@ -28,7 +28,7 @@
 
 pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
     name: "collect-intra-doc-links",
-    pass: collect_intra_doc_links,
+    run: collect_intra_doc_links,
     description: "reads a crate's documentation to resolve intra-doc-links",
 };
 
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index c00e231..da0e97f 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -9,7 +9,7 @@
 
 pub const COLLECT_TRAIT_IMPLS: Pass = Pass {
     name: "collect-trait-impls",
-    pass: collect_trait_impls,
+    run: collect_trait_impls,
     description: "retrieves trait impls for items in the crate",
 };
 
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index aebed91..355ea15 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -8,6 +8,7 @@
 use std::mem;
 use std::ops::Range;
 
+use self::Condition::*;
 use crate::clean::{self, GetDefId, Item};
 use crate::core::DocContext;
 use crate::fold::{DocFolder, StripItem};
@@ -52,10 +53,29 @@
 #[derive(Copy, Clone)]
 pub struct Pass {
     pub name: &'static str,
-    pub pass: fn(clean::Crate, &DocContext<'_>) -> clean::Crate,
+    pub run: fn(clean::Crate, &DocContext<'_>) -> clean::Crate,
     pub description: &'static str,
 }
 
+/// In a list of passes, a pass that may or may not need to be run depending on options.
+#[derive(Copy, Clone)]
+pub struct ConditionalPass {
+    pub pass: Pass,
+    pub condition: Condition,
+}
+
+/// How to decide whether to run a conditional pass.
+#[derive(Copy, Clone)]
+pub enum Condition {
+    Always,
+    /// When `--document-private-items` is passed.
+    WhenDocumentPrivate,
+    /// When `--document-private-items` is not passed.
+    WhenNotDocumentPrivate,
+    /// When `--document-hidden-items` is not passed.
+    WhenNotDocumentHidden,
+}
+
 /// The full list of passes.
 pub const PASSES: &[Pass] = &[
     CHECK_PRIVATE_ITEMS_DOC_TESTS,
@@ -72,63 +92,58 @@
 ];
 
 /// The list of passes run by default.
-pub const DEFAULT_PASSES: &[Pass] = &[
-    COLLECT_TRAIT_IMPLS,
-    COLLAPSE_DOCS,
-    UNINDENT_COMMENTS,
-    CHECK_PRIVATE_ITEMS_DOC_TESTS,
-    STRIP_HIDDEN,
-    STRIP_PRIVATE,
-    COLLECT_INTRA_DOC_LINKS,
-    CHECK_CODE_BLOCK_SYNTAX,
-    PROPAGATE_DOC_CFG,
-];
-
-/// The list of default passes run with `--document-private-items` is passed to rustdoc.
-pub const DEFAULT_PRIVATE_PASSES: &[Pass] = &[
-    COLLECT_TRAIT_IMPLS,
-    COLLAPSE_DOCS,
-    UNINDENT_COMMENTS,
-    CHECK_PRIVATE_ITEMS_DOC_TESTS,
-    STRIP_PRIV_IMPORTS,
-    COLLECT_INTRA_DOC_LINKS,
-    CHECK_CODE_BLOCK_SYNTAX,
-    PROPAGATE_DOC_CFG,
+pub const DEFAULT_PASSES: &[ConditionalPass] = &[
+    ConditionalPass::always(COLLECT_TRAIT_IMPLS),
+    ConditionalPass::always(COLLAPSE_DOCS),
+    ConditionalPass::always(UNINDENT_COMMENTS),
+    ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS),
+    ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
+    ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
+    ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate),
+    ConditionalPass::always(COLLECT_INTRA_DOC_LINKS),
+    ConditionalPass::always(CHECK_CODE_BLOCK_SYNTAX),
+    ConditionalPass::always(PROPAGATE_DOC_CFG),
 ];
 
 /// The list of default passes run when `--doc-coverage` is passed to rustdoc.
-pub const DEFAULT_COVERAGE_PASSES: &[Pass] =
-    &[COLLECT_TRAIT_IMPLS, STRIP_HIDDEN, STRIP_PRIVATE, CALCULATE_DOC_COVERAGE];
+pub const COVERAGE_PASSES: &[ConditionalPass] = &[
+    ConditionalPass::always(COLLECT_TRAIT_IMPLS),
+    ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
+    ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
+    ConditionalPass::always(CALCULATE_DOC_COVERAGE),
+];
 
-/// The list of default passes run when `--doc-coverage --document-private-items` is passed to
-/// rustdoc.
-pub const PRIVATE_COVERAGE_PASSES: &[Pass] = &[COLLECT_TRAIT_IMPLS, CALCULATE_DOC_COVERAGE];
+impl ConditionalPass {
+    pub const fn always(pass: Pass) -> Self {
+        Self::new(pass, Always)
+    }
+
+    pub const fn new(pass: Pass, condition: Condition) -> Self {
+        ConditionalPass { pass, condition }
+    }
+}
 
 /// A shorthand way to refer to which set of passes to use, based on the presence of
-/// `--no-defaults` or `--document-private-items`.
+/// `--no-defaults` and `--show-coverage`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum DefaultPassOption {
     Default,
-    Private,
     Coverage,
-    PrivateCoverage,
     None,
 }
 
 /// Returns the given default set of passes.
-pub fn defaults(default_set: DefaultPassOption) -> &'static [Pass] {
+pub fn defaults(default_set: DefaultPassOption) -> &'static [ConditionalPass] {
     match default_set {
         DefaultPassOption::Default => DEFAULT_PASSES,
-        DefaultPassOption::Private => DEFAULT_PRIVATE_PASSES,
-        DefaultPassOption::Coverage => DEFAULT_COVERAGE_PASSES,
-        DefaultPassOption::PrivateCoverage => PRIVATE_COVERAGE_PASSES,
+        DefaultPassOption::Coverage => COVERAGE_PASSES,
         DefaultPassOption::None => &[],
     }
 }
 
 /// If the given name matches a known pass, returns its information.
-pub fn find_pass(pass_name: &str) -> Option<&'static Pass> {
-    PASSES.iter().find(|p| p.name == pass_name)
+pub fn find_pass(pass_name: &str) -> Option<Pass> {
+    PASSES.iter().find(|p| p.name == pass_name).copied()
 }
 
 struct Stripper<'a> {
diff --git a/src/librustdoc/passes/private_items_doc_tests.rs b/src/librustdoc/passes/private_items_doc_tests.rs
index 23e2727..aec5a6b 100644
--- a/src/librustdoc/passes/private_items_doc_tests.rs
+++ b/src/librustdoc/passes/private_items_doc_tests.rs
@@ -5,7 +5,7 @@
 
 pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
     name: "check-private-items-doc-tests",
-    pass: check_private_items_doc_tests,
+    run: check_private_items_doc_tests,
     description: "check private items doc tests",
 };
 
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index a296e73..64b0c45 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -8,7 +8,7 @@
 
 pub const PROPAGATE_DOC_CFG: Pass = Pass {
     name: "propagate-doc-cfg",
-    pass: propagate_doc_cfg,
+    run: propagate_doc_cfg,
     description: "propagates `#[doc(cfg(...))]` to child items",
 };
 
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 08a88c0..f82e72b 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -10,7 +10,7 @@
 
 pub const STRIP_HIDDEN: Pass = Pass {
     name: "strip-hidden",
-    pass: strip_hidden,
+    run: strip_hidden,
     description: "strips all doc(hidden) items from the output",
 };
 
diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs
index af34842..35b26fb 100644
--- a/src/librustdoc/passes/strip_priv_imports.rs
+++ b/src/librustdoc/passes/strip_priv_imports.rs
@@ -5,7 +5,7 @@
 
 pub const STRIP_PRIV_IMPORTS: Pass = Pass {
     name: "strip-priv-imports",
-    pass: strip_priv_imports,
+    run: strip_priv_imports,
     description: "strips all private import statements (`use`, `extern crate`) from a crate",
 };
 
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index f4ec9cc..f244956 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -7,7 +7,7 @@
 
 pub const STRIP_PRIVATE: Pass = Pass {
     name: "strip-private",
-    pass: strip_private,
+    run: strip_private,
     description: "strips all private items from a crate which cannot be seen externally, \
         implies strip-priv-imports",
 };
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
index 3212af0..d4e09ce 100644
--- a/src/librustdoc/passes/unindent_comments.rs
+++ b/src/librustdoc/passes/unindent_comments.rs
@@ -12,7 +12,7 @@
 
 pub const UNINDENT_COMMENTS: Pass = Pass {
     name: "unindent-comments",
-    pass: unindent_comments,
+    run: unindent_comments,
     description: "removes excess indentation on comments in order for markdown to like it",
 };
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index d94e940..d89dc2a 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -1,10 +1,10 @@
-use rustc::hir::intravisit;
 use rustc::hir::map::Map;
 use rustc::session::{self, config, DiagnosticOutput};
 use rustc::util::common::ErrorReported;
 use rustc_data_structures::sync::Lrc;
 use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
+use rustc_hir::intravisit;
 use rustc_interface::interface;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
@@ -43,7 +43,7 @@
     let crate_types = if options.proc_macro_crate {
         vec![config::CrateType::ProcMacro]
     } else {
-        vec![config::CrateType::Dylib]
+        vec![config::CrateType::Rlib]
     };
 
     let sessopts = config::Options {
@@ -117,12 +117,16 @@
                     intravisit::walk_crate(this, krate);
                 });
             });
+            compiler.session().abort_if_errors();
 
             let ret: Result<_, ErrorReported> = Ok(collector.tests);
             ret
         })
-    })
-    .expect("compiler aborted in rustdoc!");
+    });
+    let tests = match tests {
+        Ok(tests) => tests,
+        Err(ErrorReported) => return 1,
+    };
 
     test_args.insert(0, "rustdoctest".to_string());
 
@@ -300,7 +304,6 @@
             eprint!("{}", self.0);
         }
     }
-
     let out = str::from_utf8(&output.stderr).unwrap();
     let _bomb = Bomb(&out);
     match (output.status.success(), compile_fail) {
@@ -310,7 +313,7 @@
         (true, false) => {}
         (false, true) => {
             if !error_codes.is_empty() {
-                error_codes.retain(|err| !out.contains(err));
+                error_codes.retain(|err| !out.contains(&format!("error[{}]: ", err)));
 
                 if !error_codes.is_empty() {
                     return Err(TestFailure::MissingErrorCodes(error_codes));
@@ -389,8 +392,8 @@
     // crate already is included.
     let result = rustc_driver::catch_fatal_errors(|| {
         with_globals(edition, || {
-            use errors::emitter::EmitterWriter;
-            use errors::Handler;
+            use rustc_errors::emitter::EmitterWriter;
+            use rustc_errors::Handler;
             use rustc_parse::maybe_new_parser_from_source_str;
             use rustc_span::source_map::FilePathMapping;
             use syntax::sess::ParseSess;
@@ -705,7 +708,7 @@
         debug!("creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
-                name: testing::DynTestName(name.clone()),
+                name: testing::DynTestName(name),
                 ignore: match config.ignore {
                     Ignore::All => true,
                     Ignore::None => false,
@@ -899,13 +902,15 @@
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'hir> {
+    type Map = Map<'hir>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
         intravisit::NestedVisitorMap::All(&self.map)
     }
 
     fn visit_item(&mut self, item: &'hir hir::Item) {
-        let name = if let hir::ItemKind::Impl(.., ref ty, _) = item.kind {
-            self.map.hir_to_pretty_string(ty.hir_id)
+        let name = if let hir::ItemKind::Impl { ref self_ty, .. } = item.kind {
+            self.map.hir_to_pretty_string(self_ty.hir_id)
         } else {
             item.ident.to_string()
         };
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index b45531d..af1c50a 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -3,7 +3,7 @@
 use std::hash::{Hash, Hasher};
 use std::path::Path;
 
-use errors::Handler;
+use rustc_errors::Handler;
 
 #[cfg(test)]
 mod tests;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 5fa9270..d3d45cc 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -558,27 +558,29 @@
                 om.trait_aliases.push(t);
             }
 
-            hir::ItemKind::Impl(
+            hir::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
+                constness,
                 ref generics,
-                ref trait_,
-                for_,
-                ref item_ids,
-            ) => {
+                ref of_trait,
+                self_ty,
+                ref items,
+            } => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
-                if !self.inlining && trait_.is_none() {
+                if !self.inlining && of_trait.is_none() {
                     let items =
-                        item_ids.iter().map(|ii| self.cx.tcx.hir().impl_item(ii.id)).collect();
+                        items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect();
                     let i = Impl {
                         unsafety,
                         polarity,
                         defaultness,
+                        constness,
                         generics,
-                        trait_,
-                        for_,
+                        trait_: of_trait,
+                        for_: self_ty,
                         items,
                         attrs: &item.attrs,
                         id: item.hir_id,
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index a22e162..c9ff93e 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -34,16 +34,6 @@
 [dev-dependencies]
 rand = "0.7"
 
-[target.x86_64-apple-darwin.dependencies]
-rustc_asan = { path = "../librustc_asan" }
-rustc_tsan = { path = "../librustc_tsan" }
-
-[target.x86_64-unknown-linux-gnu.dependencies]
-rustc_asan = { path = "../librustc_asan" }
-rustc_lsan = { path = "../librustc_lsan" }
-rustc_msan = { path = "../librustc_msan" }
-rustc_tsan = { path = "../librustc_tsan" }
-
 [target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 566e514..b48700f 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -631,6 +631,38 @@
         self.map.raw_entry_mut().from_key(&value).or_insert(value, ()).0
     }
 
+    /// Inserts an owned copy of the given `value` into the set if it is not
+    /// present, then returns a reference to the value in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(hash_set_entry)]
+    ///
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
+    ///     .iter().map(|&pet| pet.to_owned()).collect();
+    ///
+    /// assert_eq!(set.len(), 3);
+    /// for &pet in &["cat", "dog", "fish"] {
+    ///     let value = set.get_or_insert_owned(pet);
+    ///     assert_eq!(value, pet);
+    /// }
+    /// assert_eq!(set.len(), 4); // a new "fish" was inserted
+    /// ```
+    #[inline]
+    #[unstable(feature = "hash_set_entry", issue = "60896")]
+    pub fn get_or_insert_owned<Q: ?Sized>(&mut self, value: &Q) -> &T
+    where
+        T: Borrow<Q>,
+        Q: Hash + Eq + ToOwned<Owned = T>,
+    {
+        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
+        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
+        self.map.raw_entry_mut().from_key(value).or_insert_with(|| (value.to_owned(), ())).0
+    }
+
     /// Inserts a value computed from `f` into the set if the given `value` is
     /// not present, then returns a reference to the value in the set.
     ///
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 1407fe2..b480581 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -250,6 +250,7 @@
     /// assert!(
     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
     /// ```
+    #[inline]
     fn from(err: String) -> Box<dyn Error + Send + Sync> {
         struct StringError(String);
 
@@ -317,6 +318,7 @@
     /// assert!(
     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
     /// ```
+    #[inline]
     fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 267d701..941ea6a 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -44,23 +44,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn floor(self) -> f32 {
-        // On MSVC LLVM will lower many math intrinsics to a call to the
-        // corresponding function. On MSVC, however, many of these functions
-        // aren't actually available as symbols to call, but rather they are all
-        // `static inline` functions in header files. This means that from a C
-        // perspective it's "compatible", but not so much from an ABI
-        // perspective (which we're worried about).
-        //
-        // The inline header functions always just cast to a f64 and do their
-        // operation, so we do that here as well, but only for MSVC targets.
-        //
-        // Note that there are many MSVC-specific float operations which
-        // redirect to this comment, so `floorf` is just one case of a missing
-        // function on MSVC, but there are many others elsewhere.
-        #[cfg(target_env = "msvc")]
-        return (self as f64).floor() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::floorf32(self) };
+        unsafe { intrinsics::floorf32(self) }
     }
 
     /// Returns the smallest integer greater than or equal to a number.
@@ -78,11 +62,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ceil(self) -> f32 {
-        // see notes above in `floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).ceil() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::ceilf32(self) };
+        unsafe { intrinsics::ceilf32(self) }
     }
 
     /// Returns the nearest integer to a number. Round half-way cases away from
@@ -131,10 +111,10 @@
     /// ```
     /// use std::f32;
     ///
-    /// let x = 3.5_f32;
-    /// let y = -3.5_f32;
-    /// let abs_difference_x = (x.fract() - 0.5).abs();
-    /// let abs_difference_y = (y.fract() - (-0.5)).abs();
+    /// let x = 3.6_f32;
+    /// let y = -3.6_f32;
+    /// let abs_difference_x = (x.fract() - 0.6).abs();
+    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
     ///
     /// assert!(abs_difference_x <= f32::EPSILON);
     /// assert!(abs_difference_y <= f32::EPSILON);
@@ -348,14 +328,10 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powf(self, n: f32) -> f32 {
-        // see notes above in `floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).powf(n as f64) as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::powf32(self, n) };
+        unsafe { intrinsics::powf32(self, n) }
     }
 
-    /// Takes the square root of a number.
+    /// Returns the square root of a number.
     ///
     /// Returns NaN if `self` is a negative number.
     ///
@@ -399,11 +375,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn exp(self) -> f32 {
-        // see notes above in `floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).exp() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::expf32(self) };
+        unsafe { intrinsics::expf32(self) }
     }
 
     /// Returns `2^(self)`.
@@ -447,11 +419,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ln(self) -> f32 {
-        // see notes above in `floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).ln() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::logf32(self) };
+        unsafe { intrinsics::logf32(self) }
     }
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
@@ -521,11 +489,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn log10(self) -> f32 {
-        // see notes above in `floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).log10() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::log10f32(self) };
+        unsafe { intrinsics::log10f32(self) }
     }
 
     /// The positive difference of two numbers.
@@ -564,7 +528,7 @@
         unsafe { cmath::fdimf(self, other) }
     }
 
-    /// Takes the cubic root of a number.
+    /// Returns the cubic root of a number.
     ///
     /// # Examples
     ///
@@ -625,11 +589,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sin(self) -> f32 {
-        // see notes in `core::f32::Float::floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).sin() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::sinf32(self) };
+        unsafe { intrinsics::sinf32(self) }
     }
 
     /// Computes the cosine of a number (in radians).
@@ -649,11 +609,7 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cos(self) -> f32 {
-        // see notes in `core::f32::Float::floor`
-        #[cfg(target_env = "msvc")]
-        return (self as f64).cos() as f32;
-        #[cfg(not(target_env = "msvc"))]
-        return unsafe { intrinsics::cosf32(self) };
+        unsafe { intrinsics::cosf32(self) }
     }
 
     /// Computes the tangent of a number (in radians).
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index 61ce7b2..d89b38e 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -109,10 +109,10 @@
     /// # Examples
     ///
     /// ```
-    /// let x = 3.5_f64;
-    /// let y = -3.5_f64;
-    /// let abs_difference_x = (x.fract() - 0.5).abs();
-    /// let abs_difference_y = (y.fract() - (-0.5)).abs();
+    /// let x = 3.6_f64;
+    /// let y = -3.6_f64;
+    /// let abs_difference_x = (x.fract() - 0.6).abs();
+    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
     ///
     /// assert!(abs_difference_x < 1e-10);
     /// assert!(abs_difference_y < 1e-10);
@@ -323,7 +323,7 @@
         unsafe { intrinsics::powf64(self, n) }
     }
 
-    /// Takes the square root of a number.
+    /// Returns the square root of a number.
     ///
     /// Returns NaN if `self` is a negative number.
     ///
@@ -506,7 +506,7 @@
         unsafe { cmath::fdim(self, other) }
     }
 
-    /// Takes the cubic root of a number.
+    /// Returns the cubic root of a number.
     ///
     /// # Examples
     ///
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index d2ee65f..700e015 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -1187,11 +1187,6 @@
     /// function will return the corresponding [`&str`] slice. Otherwise,
     /// it will return an error with details of where UTF-8 validation failed.
     ///
-    /// > **Note**: This method is currently implemented to check for validity
-    /// > after a constant-time cast, but it is planned to alter its definition
-    /// > in the future to perform the length calculation in addition to the
-    /// > UTF-8 check whenever this method is called.
-    ///
     /// [`&str`]: ../primitive.str.html
     ///
     /// # Examples
@@ -1220,11 +1215,6 @@
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
     /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
     ///
-    /// > **Note**: This method is currently implemented to check for validity
-    /// > after a constant-time cast, but it is planned to alter its definition
-    /// > in the future to perform the length calculation in addition to the
-    /// > UTF-8 check whenever this method is called.
-    ///
     /// [`Cow`]: ../borrow/enum.Cow.html
     /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
     /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 4c30832..77da972 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -615,6 +615,7 @@
     /// assert!(!os_str.is_empty());
     /// ```
     #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+    #[inline]
     pub fn is_empty(&self) -> bool {
         self.inner.inner.is_empty()
     }
@@ -965,6 +966,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for OsString {
+    #[inline]
     fn as_ref(&self) -> &OsStr {
         self
     }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f906474..dc93ac9 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -275,7 +275,6 @@
 #![feature(link_args)]
 #![feature(linkage)]
 #![feature(log_syntax)]
-#![feature(manually_drop_take)]
 #![feature(maybe_uninit_ref)]
 #![feature(maybe_uninit_slice)]
 #![feature(needs_panic_runtime)]
@@ -294,7 +293,7 @@
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(std_internals)]
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index a9d8837..a59d7f0 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -227,10 +227,7 @@
     /// ```
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
     pub fn is_ipv4(&self) -> bool {
-        match *self {
-            SocketAddr::V4(_) => true,
-            SocketAddr::V6(_) => false,
-        }
+        matches!(*self, SocketAddr::V4(_))
     }
 
     /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
@@ -252,10 +249,7 @@
     /// ```
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
     pub fn is_ipv6(&self) -> bool {
-        match *self {
-            SocketAddr::V4(_) => false,
-            SocketAddr::V6(_) => true,
-        }
+        matches!(*self, SocketAddr::V6(_))
     }
 }
 
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 15d2361..6410a4f 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -281,10 +281,7 @@
     /// ```
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     pub fn is_ipv4(&self) -> bool {
-        match self {
-            IpAddr::V4(_) => true,
-            IpAddr::V6(_) => false,
-        }
+        matches!(self, IpAddr::V4(_))
     }
 
     /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
@@ -303,10 +300,7 @@
     /// ```
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     pub fn is_ipv6(&self) -> bool {
-        match self {
-            IpAddr::V4(_) => false,
-            IpAddr::V6(_) => true,
-        }
+        matches!(self, IpAddr::V6(_))
     }
 }
 
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 599ccc8..fee7ace 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -55,6 +55,15 @@
     fn __rust_start_panic(payload: usize) -> u32;
 }
 
+/// This function is called by the panic runtime if FFI code catches a Rust
+/// panic but doesn't rethrow it. We don't support this case since it messes
+/// with our panic count.
+#[cfg(not(test))]
+#[rustc_std_internal_symbol]
+extern "C" fn __rust_drop_panic() -> ! {
+    rtabort!("Rust panics must be rethrown");
+}
+
 #[derive(Copy, Clone)]
 enum Hook {
     Default,
@@ -199,7 +208,7 @@
                     let _ = writeln!(
                         err,
                         "note: run with `RUST_BACKTRACE=1` \
-                                           environment variable to display a backtrace."
+                                           environment variable to display a backtrace"
                     );
                 }
             }
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index f308d51..a703cb7 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -224,18 +224,12 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_verbatim(&self) -> bool {
         use self::Prefix::*;
-        match *self {
-            Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true,
-            _ => false,
-        }
+        matches!(*self, Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..))
     }
 
     #[inline]
     fn is_drive(&self) -> bool {
-        match *self {
-            Prefix::Disk(_) => true,
-            _ => false,
-        }
+        matches!(*self, Prefix::Disk(_))
     }
 
     #[inline]
@@ -1481,6 +1475,7 @@
     /// Converts a `OsString` into a `PathBuf`
     ///
     /// This conversion does not allocate or copy memory.
+    #[inline]
     fn from(s: OsString) -> PathBuf {
         PathBuf { inner: s }
     }
@@ -1541,7 +1536,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Deref for PathBuf {
     type Target = Path;
-
+    #[inline]
     fn deref(&self) -> &Path {
         Path::new(&self.inner)
     }
@@ -2661,6 +2656,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<Path> for str {
+    #[inline]
     fn as_ref(&self) -> &Path {
         Path::new(self)
     }
@@ -2675,6 +2671,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<Path> for PathBuf {
+    #[inline]
     fn as_ref(&self) -> &Path {
         self
     }
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index eddbdff..0131437 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -199,10 +199,7 @@
 
         // At this point, all spawned threads should be blocked,
         // so we shouldn't get anything from the port
-        assert!(match rx.try_recv() {
-            Err(TryRecvError::Empty) => true,
-            _ => false,
-        });
+        assert!(matches!(rx.try_recv(), Err(TryRecvError::Empty)));
 
         let mut leader_found = barrier.wait().is_leader();
 
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 5a4cb14..77e521e 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -204,9 +204,7 @@
     }
 
     /// Blocks the current thread until this condition variable receives a
-    /// notification and the required condition is met. Spurious wakeups are
-    /// ignored and this function will only return once the condition has been
-    /// met.
+    /// notification and the provided condition is false.
     ///
     /// This function will atomically unlock the mutex specified (represented by
     /// `guard`) and block the current thread. This means that any calls
@@ -228,29 +226,27 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(wait_until)]
-    ///
     /// use std::sync::{Arc, Mutex, Condvar};
     /// use std::thread;
     ///
-    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+    /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
-    ///     let mut started = lock.lock().unwrap();
-    ///     *started = true;
+    ///     let mut pending = lock.lock().unwrap();
+    ///     *pending = false;
     ///     // We notify the condvar that the value has changed.
     ///     cvar.notify_one();
     /// });
     ///
     /// // Wait for the thread to start up.
     /// let (lock, cvar) = &*pair;
-    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
-    /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
+    /// // As long as the value inside the `Mutex<bool>` is `true`, we wait.
+    /// let _guard = cvar.wait_while(lock.lock().unwrap(), |pending| { *pending }).unwrap();
     /// ```
-    #[unstable(feature = "wait_until", issue = "47960")]
-    pub fn wait_until<'a, T, F>(
+    #[stable(feature = "wait_until", since = "1.42.0")]
+    pub fn wait_while<'a, T, F>(
         &self,
         mut guard: MutexGuard<'a, T>,
         mut condition: F,
@@ -258,7 +254,7 @@
     where
         F: FnMut(&mut T) -> bool,
     {
-        while !condition(&mut *guard) {
+        while condition(&mut *guard) {
             guard = self.wait(guard)?;
         }
         Ok(guard)
@@ -343,11 +339,10 @@
     /// Condition variables normally have a boolean predicate associated with
     /// them, and the predicate must always be checked each time this function
     /// returns to protect against spurious wakeups. Additionally, it is
-    /// typically desirable for the time-out to not exceed some duration in
+    /// typically desirable for the timeout to not exceed some duration in
     /// spite of spurious wakes, thus the sleep-duration is decremented by the
-    /// amount slept. Alternatively, use the `wait_timeout_until` method
-    /// to wait until a condition is met with a total time-out regardless
-    /// of spurious wakes.
+    /// amount slept. Alternatively, use the `wait_timeout_while` method
+    /// to wait with a timeout while a predicate is true.
     ///
     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
     /// known to have elapsed.
@@ -356,7 +351,7 @@
     /// returns, regardless of whether the timeout elapsed or not.
     ///
     /// [`wait`]: #method.wait
-    /// [`wait_timeout_until`]: #method.wait_timeout_until
+    /// [`wait_timeout_while`]: #method.wait_timeout_while
     /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
     ///
     /// # Examples
@@ -407,10 +402,9 @@
     }
 
     /// Waits on this condition variable for a notification, timing out after a
-    /// specified duration. Spurious wakes will not cause this function to
-    /// return.
+    /// specified duration.
     ///
-    /// The semantics of this function are equivalent to [`wait_until`] except
+    /// The semantics of this function are equivalent to [`wait_while`] except
     /// that the thread will be blocked for roughly no longer than `dur`. This
     /// method should not be used for precise timing due to anomalies such as
     /// preemption or platform differences that may not cause the maximum
@@ -423,47 +417,45 @@
     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
     /// known to have elapsed without the condition being met.
     ///
-    /// Like [`wait_until`], the lock specified will be re-acquired when this
+    /// Like [`wait_while`], the lock specified will be re-acquired when this
     /// function returns, regardless of whether the timeout elapsed or not.
     ///
-    /// [`wait_until`]: #method.wait_until
+    /// [`wait_while`]: #method.wait_while
     /// [`wait_timeout`]: #method.wait_timeout
     /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(wait_timeout_until)]
-    ///
     /// use std::sync::{Arc, Mutex, Condvar};
     /// use std::thread;
     /// use std::time::Duration;
     ///
-    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+    /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
     ///     let (lock, cvar) = &*pair2;
-    ///     let mut started = lock.lock().unwrap();
-    ///     *started = true;
+    ///     let mut pending = lock.lock().unwrap();
+    ///     *pending = false;
     ///     // We notify the condvar that the value has changed.
     ///     cvar.notify_one();
     /// });
     ///
     /// // wait for the thread to start up
     /// let (lock, cvar) = &*pair;
-    /// let result = cvar.wait_timeout_until(
+    /// let result = cvar.wait_timeout_while(
     ///     lock.lock().unwrap(),
     ///     Duration::from_millis(100),
-    ///     |&mut started| started,
+    ///     |&mut pending| pending,
     /// ).unwrap();
     /// if result.1.timed_out() {
-    ///     // timed-out without the condition ever evaluating to true.
+    ///     // timed-out without the condition ever evaluating to false.
     /// }
     /// // access the locked mutex via result.0
     /// ```
-    #[unstable(feature = "wait_timeout_until", issue = "47960")]
-    pub fn wait_timeout_until<'a, T, F>(
+    #[stable(feature = "wait_timeout_until", since = "1.42.0")]
+    pub fn wait_timeout_while<'a, T, F>(
         &self,
         mut guard: MutexGuard<'a, T>,
         dur: Duration,
@@ -474,7 +466,7 @@
     {
         let start = Instant::now();
         loop {
-            if condition(&mut *guard) {
+            if !condition(&mut *guard) {
                 return Ok((guard, WaitTimeoutResult(false)));
             }
             let timeout = match dur.checked_sub(start.elapsed()) {
@@ -613,7 +605,6 @@
 #[cfg(test)]
 mod tests {
     use crate::sync::atomic::{AtomicBool, Ordering};
-    /// #![feature(wait_until)]
     use crate::sync::mpsc::channel;
     use crate::sync::{Arc, Condvar, Mutex};
     use crate::thread;
@@ -683,7 +674,7 @@
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
-    fn wait_until() {
+    fn wait_while() {
         let pair = Arc::new((Mutex::new(false), Condvar::new()));
         let pair2 = pair.clone();
 
@@ -698,7 +689,7 @@
 
         // Wait for the thread to start up.
         let &(ref lock, ref cvar) = &*pair;
-        let guard = cvar.wait_until(lock.lock().unwrap(), |started| *started);
+        let guard = cvar.wait_while(lock.lock().unwrap(), |started| !*started);
         assert!(*guard.unwrap());
     }
 
@@ -725,24 +716,24 @@
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    fn wait_timeout_until_wait() {
+    fn wait_timeout_while_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
 
         let g = m.lock().unwrap();
-        let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| false).unwrap();
+        let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(1), |_| true).unwrap();
         // no spurious wakeups. ensure it timed-out
         assert!(wait.timed_out());
     }
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
-    fn wait_timeout_until_instant_satisfy() {
+    fn wait_timeout_while_instant_satisfy() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
 
         let g = m.lock().unwrap();
-        let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| true).unwrap();
+        let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(0), |_| false).unwrap();
         // ensure it didn't time-out even if we were not given any time.
         assert!(!wait.timed_out());
     }
@@ -750,7 +741,7 @@
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
-    fn wait_timeout_until_wake() {
+    fn wait_timeout_while_wake() {
         let pair = Arc::new((Mutex::new(false), Condvar::new()));
         let pair_copy = pair.clone();
 
@@ -764,7 +755,7 @@
             cvar.notify_one();
         });
         let (g2, wait) = c
-            .wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| notified)
+            .wait_timeout_while(g, Duration::from_millis(u64::MAX), |&mut notified| !notified)
             .unwrap();
         // ensure it didn't time-out even if we were not given any time.
         assert!(!wait.timed_out());
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index bbe77e7..5b41525 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -118,12 +118,7 @@
     // Just tests whether this channel has been sent on or not, this is only
     // safe to use from the sender.
     pub fn sent(&self) -> bool {
-        unsafe {
-            match *self.upgrade.get() {
-                NothingSent => false,
-                _ => true,
-            }
-        }
+        unsafe { !matches!(*self.upgrade.get(), NothingSent) }
     }
 
     pub fn recv(&self, deadline: Option<Instant>) -> Result<T, Failure<T>> {
diff --git a/src/libstd/sys/cloudabi/abi/bitflags.rs b/src/libstd/sys/cloudabi/abi/bitflags.rs
index 3069362..2383277 100644
--- a/src/libstd/sys/cloudabi/abi/bitflags.rs
+++ b/src/libstd/sys/cloudabi/abi/bitflags.rs
@@ -21,9 +21,6 @@
 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 // SUCH DAMAGE.
 
-// Appease Rust's tidy.
-// ignore-license
-
 #[cfg(feature = "bitflags")]
 use bitflags::bitflags;
 
diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs
index d113a7b..b02faf18 100644
--- a/src/libstd/sys/cloudabi/abi/cloudabi.rs
+++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs
@@ -26,7 +26,6 @@
 // Source: https://github.com/NuxiNL/cloudabi
 
 // Appease Rust's tidy.
-// ignore-license
 // ignore-tidy-linelength
 
 //! **PLEASE NOTE: This entire crate including this
diff --git a/src/libstd/sys/hermit/os.rs b/src/libstd/sys/hermit/os.rs
index 5999fdd..78eabf8 100644
--- a/src/libstd/sys/hermit/os.rs
+++ b/src/libstd/sys/hermit/os.rs
@@ -6,7 +6,6 @@
 use crate::marker::PhantomData;
 use crate::memchr;
 use crate::path::{self, PathBuf};
-use crate::ptr;
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
@@ -77,13 +76,17 @@
     unsafe {
         ENV = Some(Mutex::new(HashMap::new()));
 
+        if env.is_null() {
+            return;
+        }
+
         let mut guard = ENV.as_ref().unwrap().lock().unwrap();
         let mut environ = env;
-        while environ != ptr::null() && *environ != ptr::null() {
+        while !(*environ).is_null() {
             if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 guard.insert(key, value);
             }
-            environ = environ.offset(1);
+            environ = environ.add(1);
         }
     }
 
diff --git a/src/libstd/sys/hermit/thread_local.rs b/src/libstd/sys/hermit/thread_local.rs
index ba967c7..c6f8adb 100644
--- a/src/libstd/sys/hermit/thread_local.rs
+++ b/src/libstd/sys/hermit/thread_local.rs
@@ -18,14 +18,14 @@
 static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
 
 unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
-    if KEYS == ptr::null_mut() {
+    if KEYS.is_null() {
         KEYS = Box::into_raw(Box::new(BTreeMap::new()));
     }
     &mut *KEYS
 }
 
 unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
-    if LOCALS == ptr::null_mut() {
+    if LOCALS.is_null() {
         LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
     }
     &mut *LOCALS
diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs
index 81a766e..2b0485c 100644
--- a/src/libstd/sys/sgx/abi/tls.rs
+++ b/src/libstd/sys/sgx/abi/tls.rs
@@ -70,7 +70,7 @@
             any_non_null_dtor = false;
             for (value, dtor) in TLS_KEY_IN_USE.iter().filter_map(&value_with_destructor) {
                 let value = value.replace(ptr::null_mut());
-                if value != ptr::null_mut() {
+                if !value.is_null() {
                     any_non_null_dtor = true;
                     unsafe { dtor(value) }
                 }
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index e0e6e02..4c3cb67 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -902,6 +902,12 @@
 
     /// Moves the socket into or out of nonblocking mode.
     ///
+    /// This will result in the `accept` operation becoming nonblocking,
+    /// i.e., immediately returning from their calls. If the IO operation is
+    /// successful, `Ok` is returned and no further action is required. If the
+    /// IO operation could not be completed and needs to be retried, an error
+    /// with kind [`io::ErrorKind::WouldBlock`] is returned.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -913,6 +919,8 @@
     ///     Ok(())
     /// }
     /// ```
+    ///
+    /// [`io::ErrorKind::WouldBlock`]: ../../../io/enum.ErrorKind.html#variant.WouldBlock
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 4fa9095..ab2a871 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -51,24 +51,14 @@
 
 pub struct File(FileDesc);
 
-// FIXME: This should be available on Linux with all `target_arch` and `target_env`.
-// https://github.com/rust-lang/libc/issues/1545
+// FIXME: This should be available on Linux with all `target_env`.
+// But currently only glibc exposes `statx` fn and structs.
+// We don't want to import unverified raw C structs here directly.
+// https://github.com/rust-lang/rust/pull/67774
 macro_rules! cfg_has_statx {
     ({ $($then_tt:tt)* } else { $($else_tt:tt)* }) => {
         cfg_if::cfg_if! {
-            if #[cfg(all(target_os = "linux", target_env = "gnu", any(
-                target_arch = "x86",
-                target_arch = "arm",
-                // target_arch = "mips",
-                target_arch = "powerpc",
-                target_arch = "x86_64",
-                // target_arch = "aarch64",
-                target_arch = "powerpc64",
-                // target_arch = "mips64",
-                // target_arch = "s390x",
-                target_arch = "sparc64",
-                target_arch = "riscv64",
-            )))] {
+            if #[cfg(all(target_os = "linux", target_env = "gnu"))] {
                 $($then_tt)*
             } else {
                 $($else_tt)*
@@ -76,19 +66,7 @@
         }
     };
     ($($block_inner:tt)*) => {
-        #[cfg(all(target_os = "linux", target_env = "gnu", any(
-            target_arch = "x86",
-            target_arch = "arm",
-            // target_arch = "mips",
-            target_arch = "powerpc",
-            target_arch = "x86_64",
-            // target_arch = "aarch64",
-            target_arch = "powerpc64",
-            // target_arch = "mips64",
-            // target_arch = "s390x",
-            target_arch = "sparc64",
-            target_arch = "riscv64",
-        )))]
+        #[cfg(all(target_os = "linux", target_env = "gnu"))]
         {
             $($block_inner)*
         }
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index b277b3d..91f7d15 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -480,11 +480,13 @@
         let _guard = env_lock();
         let mut environ = *environ();
         let mut result = Vec::new();
-        while environ != ptr::null() && *environ != ptr::null() {
-            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                result.push(key_value);
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
             }
-            environ = environ.offset(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/vxworks/ext/process.rs b/src/libstd/sys/vxworks/ext/process.rs
index e535c4a..31e691d 100644
--- a/src/libstd/sys/vxworks/ext/process.rs
+++ b/src/libstd/sys/vxworks/ext/process.rs
@@ -2,6 +2,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use crate::ffi::OsStr;
 use crate::io;
 use crate::process;
 use crate::sys;
@@ -105,6 +106,15 @@
     /// cross-platform `spawn` instead.
     #[stable(feature = "process_exec2", since = "1.9.0")]
     fn exec(&mut self) -> io::Error;
+
+    /// Set executable argument
+    ///
+    /// Set the first process argument, `argv[0]`, to something other than the
+    /// default executable path.
+    #[unstable(feature = "process_set_argv0", issue = "66510")]
+    fn arg0<S>(&mut self, arg: S) -> &mut process::Command
+    where
+        S: AsRef<OsStr>;
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -130,6 +140,14 @@
     fn exec(&mut self) -> io::Error {
         self.as_inner_mut().exec(sys::process::Stdio::Inherit)
     }
+
+    fn arg0<S>(&mut self, arg: S) -> &mut process::Command
+    where
+        S: AsRef<OsStr>,
+    {
+        self.as_inner_mut().set_arg_0(arg.as_ref());
+        self
+    }
 }
 
 /// Unix-specific extensions to [`process::ExitStatus`].
diff --git a/src/libstd/sys/vxworks/mod.rs b/src/libstd/sys/vxworks/mod.rs
index f102e4d..12bbfa1 100644
--- a/src/libstd/sys/vxworks/mod.rs
+++ b/src/libstd/sys/vxworks/mod.rs
@@ -36,18 +36,10 @@
 
 #[cfg(not(test))]
 pub fn init() {
-    // By default, some platforms will send a *signal* when an EPIPE error
-    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
-    // handler, causing it to kill the program, which isn't exactly what we
-    // want!
-    //
-    // Hence, we set SIGPIPE to ignore when the program starts up in order
-    // to prevent this problem.
+    // ignore SIGPIPE
     unsafe {
-        reset_sigpipe();
+        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
-
-    unsafe fn reset_sigpipe() {}
 }
 
 pub use libc::signal;
diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs
index d421915..1fadf71 100644
--- a/src/libstd/sys/vxworks/os.rs
+++ b/src/libstd/sys/vxworks/os.rs
@@ -7,7 +7,6 @@
 use crate::mem;
 use crate::memchr;
 use crate::path::{self, Path, PathBuf};
-use crate::ptr;
 use crate::slice;
 use crate::str;
 use crate::sys::cvt;
@@ -226,15 +225,15 @@
     unsafe {
         let _guard = env_lock();
         let mut environ = *environ();
-        if environ == ptr::null() {
+        if environ.is_null() {
             panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error());
         }
         let mut result = Vec::new();
-        while *environ != ptr::null() {
+        while !(*environ).is_null() {
             if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 result.push(key_value);
             }
-            environ = environ.offset(1);
+            environ = environ.add(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs
index a8139a2..6d5506b 100644
--- a/src/libstd/sys/vxworks/process/process_common.rs
+++ b/src/libstd/sys/vxworks/process/process_common.rs
@@ -90,8 +90,8 @@
         let program = os2c(program, &mut saw_nul);
         Command {
             argv: Argv(vec![program.as_ptr(), ptr::null()]),
+            args: vec![program.clone()],
             program,
-            args: Vec::new(),
             env: Default::default(),
             cwd: None,
             uid: None,
@@ -104,11 +104,19 @@
         }
     }
 
+    pub fn set_arg_0(&mut self, arg: &OsStr) {
+        // Set a new arg0
+        let arg = os2c(arg, &mut self.saw_nul);
+        debug_assert!(self.argv.0.len() > 1);
+        self.argv.0[0] = arg.as_ptr();
+        self.args[0] = arg;
+    }
+
     pub fn arg(&mut self, arg: &OsStr) {
         // Overwrite the trailing NULL pointer in `argv` and then add a new null
         // pointer.
         let arg = os2c(arg, &mut self.saw_nul);
-        self.argv.0[self.args.len() + 1] = arg.as_ptr();
+        self.argv.0[self.args.len()] = arg.as_ptr();
         self.argv.0.push(ptr::null());
 
         // Also make sure we keep track of the owned value to schedule a
@@ -133,6 +141,10 @@
         &self.argv.0
     }
 
+    pub fn get_program(&self) -> &CStr {
+        &*self.program
+    }
+
     #[allow(dead_code)]
     pub fn get_cwd(&self) -> &Option<CString> {
         &self.cwd
@@ -315,8 +327,12 @@
 
 impl fmt::Debug for Command {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self.program)?;
-        for arg in &self.args {
+        if self.program != self.args[0] {
+            write!(f, "[{:?}] ", self.program)?;
+        }
+        write!(f, "{:?}", self.args[0])?;
+
+        for arg in &self.args[1..] {
             write!(f, " {:?}", arg)?;
         }
         Ok(())
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
index ced70de..f7e84ae 100644
--- a/src/libstd/sys/vxworks/process/process_vxworks.rs
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -67,7 +67,7 @@
             let _lock = sys::os::env_lock();
 
             let ret = libc::rtpSpawn(
-                self.get_argv()[0],                             // executing program
+                self.get_program().as_ptr(),
                 self.get_argv().as_ptr() as *mut *const c_char, // argv
                 c_envp as *mut *const c_char,
                 100 as c_int, // initial priority
diff --git a/src/libstd/sys/vxworks/weak.rs b/src/libstd/sys/vxworks/weak.rs
deleted file mode 100644
index 4c6fdde..0000000
--- a/src/libstd/sys/vxworks/weak.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-//! Support for "weak linkage" to symbols on Unix
-//!
-//! Some I/O operations we do in libstd require newer versions of OSes but we
-//! need to maintain binary compatibility with older releases for now. In order
-//! to use the new functionality when available we use this module for
-//! detection.
-//!
-//! One option to use here is weak linkage, but that is unfortunately only
-//! really workable on Linux. Hence, use dlsym to get the symbol value at
-//! runtime. This is also done for compatibility with older versions of glibc,
-//! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
-//! we've been dynamically linked to the library the symbol comes from, but that
-//! is currently always the case for things like libpthread/libc.
-//!
-//! A long time ago this used weak linkage for the __pthread_get_minstack
-//! symbol, but that caused Debian to detect an unnecessarily strict versioned
-//! dependency on libc6 (#23628).
-
-use crate::ffi::CStr;
-use crate::marker;
-use crate::mem;
-use crate::sync::atomic::{AtomicUsize, Ordering};
-
-pub struct Weak<F> {
-    name: &'static str,
-    addr: AtomicUsize,
-    _marker: marker::PhantomData<F>,
-}
-
-impl<F> Weak<F> {
-    pub const fn new(name: &'static str) -> Weak<F> {
-        Weak { name, addr: AtomicUsize::new(1), _marker: marker::PhantomData }
-    }
-
-    pub fn get(&self) -> Option<F> {
-        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
-        unsafe {
-            if self.addr.load(Ordering::SeqCst) == 1 {
-                self.addr.store(fetch(self.name), Ordering::SeqCst);
-            }
-            match self.addr.load(Ordering::SeqCst) {
-                0 => None,
-                addr => Some(mem::transmute_copy::<usize, F>(&addr)),
-            }
-        }
-    }
-}
-
-unsafe fn fetch(name: &str) -> usize {
-    let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
-        Ok(cstr) => cstr,
-        Err(..) => return 0,
-    };
-    assert!(false, "FIXME: fetch");
-    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
-}
diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs
index 3baec6b..8052c0a 100644
--- a/src/libstd/sys/wasi/os.rs
+++ b/src/libstd/sys/wasi/os.rs
@@ -6,7 +6,6 @@
 use crate::marker::PhantomData;
 use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::ptr;
 use crate::str;
 use crate::sys::memchr;
 use crate::sys::{unsupported, Void};
@@ -107,11 +106,13 @@
         let _guard = env_lock();
         let mut environ = libc::environ;
         let mut result = Vec::new();
-        while environ != ptr::null_mut() && *environ != ptr::null_mut() {
-            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
-                result.push(key_value);
+        if !environ.is_null() {
+            while !(*environ).is_null() {
+                if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                    result.push(key_value);
+                }
+                environ = environ.add(1);
             }
-            environ = environ.offset(1);
         }
         return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData };
     }
diff --git a/src/libstd/sys/windows/cmath.rs b/src/libstd/sys/windows/cmath.rs
index 6f5d40b..1a5421f 100644
--- a/src/libstd/sys/windows/cmath.rs
+++ b/src/libstd/sys/windows/cmath.rs
@@ -27,7 +27,7 @@
 
 pub use self::shims::*;
 
-#[cfg(not(target_env = "msvc"))]
+#[cfg(not(all(target_env = "msvc", target_arch = "x86")))]
 mod shims {
     use libc::c_float;
 
@@ -43,10 +43,10 @@
     }
 }
 
-// On MSVC these functions aren't defined, so we just define shims which promote
-// everything fo f64, perform the calculation, and then demote back to f32.
-// While not precisely correct should be "correct enough" for now.
-#[cfg(target_env = "msvc")]
+// On 32-bit x86 MSVC these functions aren't defined, so we just define shims
+// which promote everything fo f64, perform the calculation, and then demote
+// back to f32. While not precisely correct should be "correct enough" for now.
+#[cfg(all(target_env = "msvc", target_arch = "x86"))]
 mod shims {
     use libc::c_float;
 
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index c535467..cc4ae40 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -43,7 +43,7 @@
             ];
             module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
 
-            if module != ptr::null_mut() {
+            if !module.is_null() {
                 errnum ^= c::FACILITY_NT_BIT as i32;
                 flags = c::FORMAT_MESSAGE_FROM_HMODULE;
             }
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index c7d4828..135e830 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -13,75 +13,43 @@
 
 use libc::{c_int, c_void};
 
-#[cfg(not(any(
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "macos",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "solaris",
-    target_os = "haiku",
-    target_os = "l4re"
-)))]
-use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP;
-#[cfg(not(any(
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "macos",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "solaris",
-    target_os = "haiku",
-    target_os = "l4re"
-)))]
-use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP;
-#[cfg(any(
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "macos",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "solaris",
-    target_os = "haiku",
-    target_os = "l4re"
-))]
-use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
-#[cfg(any(
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "macos",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "solaris",
-    target_os = "haiku",
-    target_os = "l4re"
-))]
-use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
+cfg_if::cfg_if! {
+    if #[cfg(any(
+        target_os = "dragonfly", target_os = "freebsd",
+        target_os = "ios", target_os = "macos",
+        target_os = "openbsd", target_os = "netbsd",
+        target_os = "solaris", target_os = "haiku", target_os = "l4re"))] {
+        use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
+        use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
+    } else {
+        use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP;
+        use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP;
+    }
+}
 
-#[cfg(any(
-    target_os = "linux",
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "haiku"
-))]
-use libc::MSG_NOSIGNAL;
-#[cfg(not(any(
-    target_os = "linux",
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "haiku"
-)))]
-const MSG_NOSIGNAL: c_int = 0x0;
+cfg_if::cfg_if! {
+    if #[cfg(any(
+        target_os = "linux", target_os = "android",
+        target_os = "dragonfly", target_os = "freebsd",
+        target_os = "openbsd", target_os = "netbsd",
+        target_os = "haiku"))] {
+        use libc::MSG_NOSIGNAL;
+    } else {
+        const MSG_NOSIGNAL: c_int = 0x0;
+    }
+}
+
+cfg_if::cfg_if! {
+    if #[cfg(any(
+        target_os = "dragonfly", target_os = "freebsd",
+        target_os = "openbsd", target_os = "netbsd",
+        target_os = "solaris"))] {
+        use libc::c_uchar;
+        type IpV4MultiCastType = c_uchar;
+    } else {
+        type IpV4MultiCastType = c_int;
+    }
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 // sockaddr and misc bindings
@@ -566,20 +534,30 @@
     }
 
     pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
-        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP, multicast_loop_v4 as c_int)
+        setsockopt(
+            &self.inner,
+            c::IPPROTO_IP,
+            c::IP_MULTICAST_LOOP,
+            multicast_loop_v4 as IpV4MultiCastType,
+        )
     }
 
     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
+        let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
         Ok(raw != 0)
     }
 
     pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
-        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, multicast_ttl_v4 as c_int)
+        setsockopt(
+            &self.inner,
+            c::IPPROTO_IP,
+            c::IP_MULTICAST_TTL,
+            multicast_ttl_v4 as IpV4MultiCastType,
+        )
     }
 
     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
+        let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
         Ok(raw as u32)
     }
 
diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs
index eb8a881..e965ea7 100644
--- a/src/libstd/sys_common/os_str_bytes.rs
+++ b/src/libstd/sys_common/os_str_bytes.rs
@@ -104,6 +104,7 @@
         self.inner.shrink_to(min_capacity)
     }
 
+    #[inline]
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 0dce8f8..5bc8fe5 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -65,9 +65,9 @@
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | Cloud ABI | [clock_time_get (Monotonic Clock)]                                   |
+/// | CloudABI  | [clock_time_get (Monotonic Clock)]                                   |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
-/// | UNIX      | [clock_time_get (Monotonic Clock)]                                   |
+/// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
 /// | VXWorks   | [clock_gettime (Monotonic Clock)]                                    |
 /// | WASI      | [__wasi_clock_time_get (Monotonic Clock)]                            |
@@ -79,7 +79,7 @@
 /// [__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
+/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 ///
 /// **Disclaimer:** These system calls might change over time.
 ///
@@ -144,7 +144,7 @@
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | Cloud ABI | [clock_time_get (Realtime Clock)]                                    |
+/// | CloudABI  | [clock_time_get (Realtime Clock)]                                    |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
 /// | DARWIN    | [gettimeofday]                                                       |
@@ -152,7 +152,7 @@
 /// | WASI      | [__wasi_clock_time_get (Realtime Clock)]                             |
 /// | Windows   | [GetSystemTimeAsFileTime]                                            |
 ///
-/// [clock_time_get (Realtime Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt
+/// [clock_time_get (Realtime Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 /// [`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
 /// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 2098656..2e647d2a 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -10,18 +10,15 @@
 doctest = false
 
 [dependencies]
-bitflags = "1.2.1"
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 log = "0.4"
 scoped-tls = "1.0"
-lazy_static = "1.0.0"
+rustc_errors = { path = "../librustc_errors" }
 rustc_span = { path = "../librustc_span" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_macros = { path = "../librustc_macros" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 4707026..5f38ac4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -266,12 +266,24 @@
 /// small, positive ids.
 pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
 
-/// A modifier on a bound, currently this is only used for `?Sized`, where the
-/// modifier is `Maybe`. Negative bounds should also be handled here.
+/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
+///
+/// Negative bounds should also be handled here.
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
 pub enum TraitBoundModifier {
+    /// No modifiers
     None,
+
+    /// `?Trait`
     Maybe,
+
+    /// `?const Trait`
+    MaybeConst,
+
+    /// `?const ?Trait`
+    //
+    // This parses but will be rejected during AST validation.
+    MaybeConstMaybe,
 }
 
 /// The AST represents all type param bounds as types.
@@ -649,7 +661,7 @@
     Lit(P<Expr>),
 
     /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
-    Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
+    Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
 
     /// A slice pattern `[a, b, c]`.
     Slice(Vec<P<Pat>>),
@@ -1441,8 +1453,8 @@
     pub legacy: bool,
 }
 
-// Clippy uses Hash and PartialEq
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq, HashStable_Generic)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)]
+#[derive(HashStable_Generic)]
 pub enum StrStyle {
     /// A regular string, like `"foo"`.
     Cooked,
@@ -1491,9 +1503,9 @@
     }
 }
 
-// Clippy uses Hash and PartialEq
 /// Type of the integer literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
+#[derive(HashStable_Generic)]
 pub enum LitIntType {
     /// e.g. `42_i32`.
     Signed(IntTy),
@@ -1504,7 +1516,8 @@
 }
 
 /// Type of the float literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
+#[derive(HashStable_Generic)]
 pub enum LitFloatType {
     /// A float literal with a suffix (`1f32` or `1E10f32`).
     Suffixed(FloatTy),
@@ -1515,8 +1528,7 @@
 /// Literal kind.
 ///
 /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
-// Clippy uses Hash and PartialEq
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
 pub enum LitKind {
     /// A string literal (`"foo"`).
     Str(Symbol, StrStyle),
@@ -2158,7 +2170,8 @@
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(HashStable_Generic)]
 pub enum Constness {
     Const,
     NotConst,
@@ -2600,15 +2613,19 @@
     /// An implementation.
     ///
     /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
-    Impl(
-        Unsafety,
-        ImplPolarity,
-        Defaultness,
-        Generics,
-        Option<TraitRef>, // (optional) trait this impl implements
-        P<Ty>,            // self
-        Vec<AssocItem>,
-    ),
+    Impl {
+        unsafety: Unsafety,
+        polarity: ImplPolarity,
+        defaultness: Defaultness,
+        constness: Constness,
+        generics: Generics,
+
+        /// The trait being implemented, if any.
+        of_trait: Option<TraitRef>,
+
+        self_ty: P<Ty>,
+        items: Vec<AssocItem>,
+    },
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
@@ -2635,7 +2652,7 @@
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) => "item",
+            ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl { .. } => "item",
         }
     }
 }
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 04c28dd..6cfe4f2 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -2,19 +2,16 @@
 
 use super::{mark_used, MetaItemKind};
 use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
-use crate::feature_gate::feature_err;
 use crate::print::pprust;
-use crate::sess::ParseSess;
+use crate::sess::{feature_err, ParseSess};
 
-use errors::{Applicability, Handler};
+use rustc_errors::{struct_span_err, Applicability, Handler};
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
 use rustc_macros::HashStable_Generic;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{symbol::sym, symbol::Symbol, Span};
 use std::num::NonZeroU32;
 
-use rustc_error_codes::*;
-
 pub fn is_builtin_attr(attr: &Attribute) -> bool {
     attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
 }
@@ -31,17 +28,21 @@
 fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     let diag = &sess.span_diagnostic;
     match error {
-        AttrError::MultipleItem(item) => span_err!(diag, span, E0538, "multiple '{}' items", item),
+        AttrError::MultipleItem(item) => {
+            struct_span_err!(diag, span, E0538, "multiple '{}' items", item).emit();
+        }
         AttrError::UnknownMetaItem(item, expected) => {
             let expected = expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
             struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item)
                 .span_label(span, format!("expected one of {}", expected.join(", ")))
                 .emit();
         }
-        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
-        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
+        AttrError::MissingSince => struct_span_err!(diag, span, E0542, "missing 'since'").emit(),
+        AttrError::MissingFeature => {
+            struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
+        }
         AttrError::MultipleStabilityLevels => {
-            span_err!(diag, span, E0544, "multiple stability levels")
+            struct_span_err!(diag, span, E0544, "multiple stability levels").emit();
         }
         AttrError::UnsupportedLiteral(msg, is_bytestr) => {
             let mut err = struct_span_err!(diag, span, E0565, "{}", msg);
@@ -283,7 +284,7 @@
                     *item = Some(v);
                     true
                 } else {
-                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
+                    struct_span_err!(diagnostic, meta.span, E0539, "incorrect meta item").emit();
                     false
                 }
             };
@@ -331,12 +332,13 @@
             match meta_name {
                 sym::rustc_deprecated => {
                     if rustc_depr.is_some() {
-                        span_err!(
+                        struct_span_err!(
                             diagnostic,
                             item_sp,
                             E0540,
                             "multiple rustc_deprecated attributes"
-                        );
+                        )
+                        .emit();
                         continue 'outer;
                     }
 
@@ -351,7 +353,8 @@
                             continue;
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span, E0543, "missing 'reason'");
+                            struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'")
+                                .emit();
                             continue;
                         }
                     }
@@ -426,12 +429,13 @@
                                         // Disallowing this requires updates to some submodules
                                         NonZeroU32::new(num)
                                     } else {
-                                        span_err!(
+                                        struct_span_err!(
                                             diagnostic,
                                             attr.span,
                                             E0545,
                                             "incorrect 'issue'"
-                                        );
+                                        )
+                                        .emit();
                                         continue;
                                     }
                                 }
@@ -453,7 +457,8 @@
                             continue;
                         }
                         _ => {
-                            span_err!(diagnostic, attr.span, E0547, "missing 'issue'");
+                            struct_span_err!(diagnostic, attr.span, E0547, "missing 'issue'")
+                                .emit();
                             continue;
                         }
                     }
@@ -539,13 +544,14 @@
         if let Some(ref mut stab) = stab {
             stab.rustc_depr = Some(rustc_depr);
         } else {
-            span_err!(
+            struct_span_err!(
                 diagnostic,
                 item_sp,
                 E0549,
                 "rustc_deprecated attribute must be paired with \
                        either stable or unstable attribute"
-            );
+            )
+            .emit();
         }
     }
 
@@ -555,14 +561,15 @@
             stab.promotable = promotable;
             stab.allow_const_fn_ptr = allow_const_fn_ptr;
         } else {
-            span_err!(
+            struct_span_err!(
                 diagnostic,
                 item_sp,
                 E0717,
                 "rustc_promotable and rustc_allow_const_fn_ptr attributes \
                       must be paired with either a rustc_const_unstable or a rustc_const_stable \
                       attribute"
-            );
+            )
+            .emit();
         }
     }
 
@@ -649,20 +656,27 @@
                 }
                 sym::not => {
                     if mis.len() != 1 {
-                        span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
+                        struct_span_err!(
+                            sess.span_diagnostic,
+                            cfg.span,
+                            E0536,
+                            "expected 1 cfg-pattern"
+                        )
+                        .emit();
                         return false;
                     }
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, eval)
                 }
                 _ => {
-                    span_err!(
+                    struct_span_err!(
                         sess.span_diagnostic,
                         cfg.span,
                         E0537,
                         "invalid predicate `{}`",
                         pprust::path_to_string(&cfg.path)
-                    );
+                    )
+                    .emit();
                     false
                 }
             }
@@ -703,7 +717,7 @@
         }
 
         if depr.is_some() {
-            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
+            struct_span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes").emit();
             break;
         }
 
@@ -741,7 +755,8 @@
                                 ),
                             );
                         } else {
-                            span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
+                            struct_span_err!(diagnostic, meta.span, E0551, "incorrect meta item")
+                                .emit();
                         }
 
                         false
@@ -900,13 +915,14 @@
                         };
                     }
                     if let Some(literal_error) = literal_error {
-                        span_err!(
+                        struct_span_err!(
                             diagnostic,
                             item.span(),
                             E0589,
                             "invalid `repr(align)` attribute: {}",
                             literal_error
-                        );
+                        )
+                        .emit();
                     }
                 } else {
                     if let Some(meta_item) = item.meta_item() {
@@ -945,7 +961,13 @@
                 }
                 if !recognised {
                     // Not a word we recognize
-                    span_err!(diagnostic, item.span(), E0552, "unrecognized representation hint");
+                    struct_span_err!(
+                        diagnostic,
+                        item.span(),
+                        E0552,
+                        "unrecognized representation hint"
+                    )
+                    .emit();
                 }
             }
         }
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 8449b61..ec05dab 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -384,7 +384,7 @@
 
 pub fn allow_internal_unstable<'a>(
     attrs: &[Attribute],
-    span_diagnostic: &'a errors::Handler,
+    span_diagnostic: &'a rustc_errors::Handler,
 ) -> Option<impl Iterator<Item = Symbol> + 'a> {
     find_by_name(attrs, sym::allow_internal_unstable).and_then(|attr| {
         attr.meta_item_list()
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
deleted file mode 100644
index 4ed1741..0000000
--- a/src/libsyntax/diagnostics/macros.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-#[macro_export]
-macro_rules! diagnostic_used {
-    ($code:ident) => {
-        let _ = $code;
-    };
-}
-
-#[macro_export]
-macro_rules! span_fatal {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_fatal_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_err {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_err_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_warn {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.span_warn_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_err {
-    ($session:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_err_with_code(
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! span_err_or_warn {
-    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        if $is_warning {
-            $session.span_warn_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        } else {
-            $session.span_err_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_fatal {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_fatal_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_err {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_err_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! stringify_error_code {
-    ($code:ident) => {{
-        $crate::diagnostic_used!($code);
-        $crate::errors::DiagnosticId::Error(stringify!($code).to_owned())
-    }};
-}
-
-#[macro_export]
-macro_rules! type_error_struct {
-    ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
-        if $typ.references_error() {
-            $session.diagnostic().struct_dummy()
-        } else {
-            struct_span_err!($session, $span, $code, $($message)*)
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_warn {
-    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        $session.struct_span_warn_with_code(
-            $span,
-            &format!($($message)*),
-            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-        )
-    })
-}
-
-#[macro_export]
-macro_rules! struct_span_err_or_warn {
-    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $crate::diagnostic_used!($code);
-        if $is_warning {
-            $session.struct_span_warn_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        } else {
-            $session.struct_span_err_with_code(
-                $span,
-                &format!($($message)*),
-                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
-            )
-        }
-    })
-}
-
-#[macro_export]
-macro_rules! span_note {
-    ($err:expr, $span:expr, $($message:tt)*) => ({
-        ($err).span_note($span, &format!($($message)*));
-    })
-}
-
-#[macro_export]
-macro_rules! span_help {
-    ($err:expr, $span:expr, $($message:tt)*) => ({
-        ($err).span_help($span, &format!($($message)*));
-    })
-}
-
-#[macro_export]
-macro_rules! help {
-    ($err:expr, $($message:tt)*) => ({
-        ($err).help(&format!($($message)*));
-    })
-}
diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs
deleted file mode 100644
index 7724107..0000000
--- a/src/libsyntax/early_buffered_lints.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! Allows the buffering of lints for later.
-//!
-//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat
-//! redundant. Later, these types can be converted to types for use by the rest of the compiler.
-
-use rustc_session::declare_lint;
-pub use rustc_session::lint::BufferedEarlyLint;
-use rustc_session::lint::FutureIncompatibleInfo;
-
-declare_lint! {
-    pub ILL_FORMED_ATTRIBUTE_INPUT,
-    Deny,
-    "ill-formed attribute inputs that were previously accepted and used in practice",
-    @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
-        edition: None,
-    };
-}
-
-declare_lint! {
-    pub META_VARIABLE_MISUSE,
-    Allow,
-    "possible meta-variable misuse at macro definition"
-}
-
-declare_lint! {
-    pub INCOMPLETE_INCLUDE,
-    Deny,
-    "trailing content in included file"
-}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 72beddf..b0c2aa3 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -7,18 +7,17 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(bool_to_option)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
+#![feature(const_fn)] // For the `transmute` in `P::new`
 #![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(try_trait)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(unicode_internals)]
 #![recursion_limit = "256"]
 
 use ast::AttrId;
-pub use errors;
 use rustc_data_structures::sync::Lock;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
@@ -62,12 +61,6 @@
 
 scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
 
-#[macro_use]
-pub mod diagnostics {
-    #[macro_use]
-    pub mod macros;
-}
-
 pub mod util {
     pub mod classify;
     pub mod comments;
@@ -82,13 +75,8 @@
 pub mod attr;
 pub mod entry;
 pub mod expand;
-pub mod feature_gate {
-    mod check;
-    pub use check::{check_attribute, check_crate, feature_err, feature_err_issue, get_features};
-}
 pub mod mut_visit;
 pub mod ptr;
-pub mod show_span;
 pub use rustc_session::parse as sess;
 pub mod token;
 pub mod tokenstream;
@@ -100,8 +88,6 @@
     pub mod pprust;
 }
 
-pub mod early_buffered_lints;
-
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 1413f15..4a460c5 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -917,10 +917,19 @@
             vis.visit_variant_data(variant_data);
             vis.visit_generics(generics);
         }
-        ItemKind::Impl(_unsafety, _polarity, _defaultness, generics, trait_ref, ty, items) => {
+        ItemKind::Impl {
+            unsafety: _,
+            polarity: _,
+            defaultness: _,
+            constness: _,
+            generics,
+            of_trait,
+            self_ty,
+            items,
+        } => {
             vis.visit_generics(generics);
-            visit_opt(trait_ref, |trait_ref| vis.visit_trait_ref(trait_ref));
-            vis.visit_ty(ty);
+            visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
+            vis.visit_ty(self_ty);
             items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
         }
         ItemKind::Trait(_is_auto, _unsafety, generics, bounds, items) => {
@@ -1074,8 +1083,8 @@
         PatKind::Box(inner) => vis.visit_pat(inner),
         PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
         PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
-            vis.visit_expr(e1);
-            vis.visit_expr(e2);
+            visit_opt(e1, |e| vis.visit_expr(e));
+            visit_opt(e2, |e| vis.visit_expr(e));
             vis.visit_span(span);
         }
         PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index dd99765..d6f18fd 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -548,11 +548,7 @@
         let st = match style {
             ast::StrStyle::Cooked => (format!("\"{}\"", st.escape_debug())),
             ast::StrStyle::Raw(n) => {
-                (format!(
-                    "r{delim}\"{string}\"{delim}",
-                    delim = "#".repeat(n as usize),
-                    string = st
-                ))
+                format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = st)
             }
         };
         self.word(st)
@@ -1226,20 +1222,22 @@
                 self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, item.ident, item.span, true);
             }
-            ast::ItemKind::Impl(
+            ast::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
+                constness,
                 ref generics,
-                ref opt_trait,
-                ref ty,
-                ref impl_items,
-            ) => {
+                ref of_trait,
+                ref self_ty,
+                ref items,
+            } => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
                 self.print_unsafety(unsafety);
                 self.word_nbsp("impl");
+                self.print_constness(constness);
 
                 if !generics.params.is_empty() {
                     self.print_generic_params(&generics.params);
@@ -1250,19 +1248,19 @@
                     self.s.word("!");
                 }
 
-                if let Some(ref t) = *opt_trait {
+                if let Some(ref t) = *of_trait {
                     self.print_trait_ref(t);
                     self.s.space();
                     self.word_space("for");
                 }
 
-                self.print_type(ty);
+                self.print_type(self_ty);
                 self.print_where_clause(&generics.where_clause);
 
                 self.s.space();
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
-                for impl_item in impl_items {
+                for impl_item in items {
                     self.print_assoc_item(impl_item);
                 }
                 self.bclose(item.span);
@@ -1643,7 +1641,7 @@
                     self.print_expr_as_cond(i);
                     self.s.space();
                     self.print_block(then);
-                    self.print_else(e.as_ref().map(|e| &**e))
+                    self.print_else(e.as_deref())
                 }
                 // Final `else` block.
                 ast::ExprKind::Block(ref b, _) => {
@@ -1947,7 +1945,7 @@
                 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));
+                self.print_if(test, blk, elseopt.as_deref())
             }
             ast::ExprKind::While(ref test, ref blk, opt_label) => {
                 if let Some(label) = opt_label {
@@ -2329,14 +2327,18 @@
             }
             PatKind::Lit(ref e) => self.print_expr(&**e),
             PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
-                self.print_expr(begin);
-                self.s.space();
+                if let Some(e) = begin {
+                    self.print_expr(e);
+                    self.s.space();
+                }
                 match *end_kind {
                     RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."),
                     RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="),
                     RangeEnd::Excluded => self.s.word(".."),
                 }
-                self.print_expr(end);
+                if let Some(e) = end {
+                    self.print_expr(e);
+                }
             }
             PatKind::Slice(ref elts) => {
                 self.s.word("[");
@@ -2769,6 +2771,13 @@
         }
     }
 
+    crate fn print_constness(&mut self, s: ast::Constness) {
+        match s {
+            ast::Constness::Const => self.word_nbsp("const"),
+            ast::Constness::NotConst => {}
+        }
+    }
+
     crate fn print_is_auto(&mut self, s: ast::IsAuto) {
         match s {
             ast::IsAuto::Yes => self.word_nbsp("auto"),
diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs
index fc69702..cce86fe 100644
--- a/src/libsyntax/util/lev_distance.rs
+++ b/src/libsyntax/util/lev_distance.rs
@@ -54,14 +54,16 @@
     T: Iterator<Item = &'a Symbol>,
 {
     let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
+    let name_vec: Vec<&Symbol> = iter_names.collect();
 
-    let (case_insensitive_match, levenstein_match) = iter_names
+    let (case_insensitive_match, levenshtein_match) = name_vec
+        .iter()
         .filter_map(|&name| {
             let dist = lev_distance(lookup, &name.as_str());
             if dist <= max_dist { Some((name, dist)) } else { None }
         })
         // Here we are collecting the next structure:
-        // (case_insensitive_match, (levenstein_match, levenstein_distance))
+        // (case_insensitive_match, (levenshtein_match, levenshtein_distance))
         .fold((None, None), |result, (candidate, dist)| {
             (
                 if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
@@ -75,10 +77,31 @@
                 },
             )
         });
-
+    // Priority of matches:
+    // 1. Exact case insensitive match
+    // 2. Levenshtein distance match
+    // 3. Sorted word match
     if let Some(candidate) = case_insensitive_match {
-        Some(candidate) // exact case insensitive match has a higher priority
+        Some(*candidate)
+    } else if levenshtein_match.is_some() {
+        levenshtein_match.map(|(candidate, _)| *candidate)
     } else {
-        levenstein_match.map(|(candidate, _)| candidate)
+        find_match_by_sorted_words(name_vec, lookup)
     }
 }
+
+fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> {
+    iter_names.iter().fold(None, |result, candidate| {
+        if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
+            Some(**candidate)
+        } else {
+            result
+        }
+    })
+}
+
+fn sort_by_words(name: &str) -> String {
+    let mut split_words: Vec<&str> = name.split('_').collect();
+    split_words.sort();
+    split_words.join("_")
+}
diff --git a/src/libsyntax/util/lev_distance/tests.rs b/src/libsyntax/util/lev_distance/tests.rs
index f65f927..2226616 100644
--- a/src/libsyntax/util/lev_distance/tests.rs
+++ b/src/libsyntax/util/lev_distance/tests.rs
@@ -46,5 +46,11 @@
             find_best_match_for_name(input.iter(), "aaaa", Some(4)),
             Some(Symbol::intern("AAAA"))
         );
+
+        let input = vec![Symbol::intern("a_longer_variable_name")];
+        assert_eq!(
+            find_best_match_for_name(input.iter(), "a_variable_longer_name", None),
+            Some(Symbol::intern("a_longer_variable_name"))
+        );
     })
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ebb49ab..946a0d2 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -308,11 +308,20 @@
             visitor.visit_generics(generics);
             visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
         }
-        ItemKind::Impl(_, _, _, ref generics, ref opt_trait_reference, ref typ, ref impl_items) => {
+        ItemKind::Impl {
+            unsafety: _,
+            polarity: _,
+            defaultness: _,
+            constness: _,
+            ref generics,
+            ref of_trait,
+            ref self_ty,
+            ref items,
+        } => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
-            visitor.visit_ty(typ);
-            walk_list!(visitor, visit_impl_item, impl_items);
+            walk_list!(visitor, visit_trait_ref, of_trait);
+            visitor.visit_ty(self_ty);
+            walk_list!(visitor, visit_impl_item, items);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
@@ -492,8 +501,8 @@
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound);
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild | PatKind::Rest => {}
         PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => {
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index d2e3b07..2116b43 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -91,7 +91,7 @@
 #[allow(missing_docs)]
 pub mod color {
     /// Number for a terminal color
-    pub type Color = u16;
+    pub type Color = u32;
 
     pub const BLACK: Color = 0;
     pub const RED: Color = 1;
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index f1adc53..918875e 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -24,7 +24,7 @@
     /// Map of capability name to boolean value
     pub bools: HashMap<String, bool>,
     /// Map of capability name to numeric value
-    pub numbers: HashMap<String, u16>,
+    pub numbers: HashMap<String, u32>,
     /// Map of capability name to raw (unexpanded) string
     pub strings: HashMap<String, Vec<u8>>,
 }
@@ -129,7 +129,7 @@
 /// A Terminal that knows how many colors it supports, with a reference to its
 /// parsed Terminfo database record.
 pub struct TerminfoTerminal<T> {
-    num_colors: u16,
+    num_colors: u32,
     out: T,
     ti: TermInfo,
 }
diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs
index d36adb7..fbc5aeb 100644
--- a/src/libterm/terminfo/parser/compiled.rs
+++ b/src/libterm/terminfo/parser/compiled.rs
@@ -159,16 +159,16 @@
 
 fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
     let mut b = [0; 2];
-    let mut amt = 0;
-    while amt < b.len() {
-        match r.read(&mut b[amt..])? {
-            0 => return Err(io::Error::new(io::ErrorKind::Other, "end of file")),
-            n => amt += n,
-        }
-    }
+    r.read_exact(&mut b)?;
     Ok((b[0] as u16) | ((b[1] as u16) << 8))
 }
 
+fn read_le_u32(r: &mut dyn io::Read) -> io::Result<u32> {
+    let mut b = [0; 4];
+    r.read_exact(&mut b)?;
+    Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24))
+}
+
 fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
     match r.bytes().next() {
         Some(s) => s,
@@ -194,9 +194,12 @@
 
     // Check magic number
     let magic = t!(read_le_u16(file));
-    if magic != 0x011A {
-        return Err(format!("invalid magic number: expected {:x}, found {:x}", 0x011A, magic));
-    }
+
+    let extended = match magic {
+        0o0432 => false,
+        0o01036 => true,
+        _ => return Err(format!("invalid magic number, found {:o}", magic)),
+    };
 
     // According to the spec, these fields must be >= -1 where -1 means that the feature is not
     // supported. Using 0 instead of -1 works because we skip sections with length 0.
@@ -258,11 +261,15 @@
         t!(read_byte(file)); // compensate for padding
     }
 
-    let numbers_map: HashMap<String, u16> = t! {
-        (0..numbers_count).filter_map(|i| match read_le_u16(file) {
-            Ok(0xFFFF) => None,
-            Ok(n) => Some(Ok((nnames[i].to_string(), n))),
-            Err(e) => Some(Err(e))
+    let numbers_map: HashMap<String, u32> = t! {
+        (0..numbers_count).filter_map(|i| {
+            let number = if extended { read_le_u32(file) } else { read_le_u16(file).map(Into::into) };
+
+            match number {
+                Ok(0xFFFF) => None,
+                Ok(n) => Some(Ok((nnames[i].to_string(), n))),
+                Err(e) => Some(Err(e))
+            }
         }).collect()
     };
 
@@ -318,7 +325,7 @@
     strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());
 
     let mut numbers = HashMap::new();
-    numbers.insert("colors".to_string(), 8u16);
+    numbers.insert("colors".to_string(), 8);
 
     TermInfo {
         names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
index b6c607a..c24cf951 100644
--- a/src/libterm/win.rs
+++ b/src/libterm/win.rs
@@ -89,7 +89,7 @@
         _ => unreachable!(),
     };
 
-    color | (bits & 0x8) // copy the hi-intensity bit
+    color | (u32::from(bits) & 0x8) // copy the hi-intensity bit
 }
 
 impl<T: Write + Send + 'static> WinConsole<T> {
diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs
index ea6d632..edff8be 100644
--- a/src/libtest/cli.rs
+++ b/src/libtest/cli.rs
@@ -125,6 +125,8 @@
             `RUST_TEST_TIME_DOCTEST` environment variables.
 
             Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+            Durations must be specified in milliseconds, e.g. `500,2000` means that the warn time
+            is 0.5 seconds, and the critical time is 2 seconds.
 
             Not available for --format=terse",
             "plain|colored",
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 884db85..e994731 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -153,12 +153,13 @@
     // If we're being run in SpawnedSecondary mode, run the test here. run_test
     // will then exit the process.
     if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) {
+        env::remove_var(SECONDARY_TEST_INVOKER_VAR);
         let test = tests
             .iter()
             .filter(|test| test.desc.name.as_slice() == name)
             .map(make_owned_test)
             .next()
-            .expect("couldn't find a test with the provided name");
+            .expect(&format!("couldn't find a test with the provided name '{}'", name));
         let TestDescAndFn { desc, testfn } = test;
         let testfn = match testfn {
             StaticTestFn(f) => f,
@@ -485,9 +486,7 @@
         }
         StaticBenchFn(benchfn) => {
             // Benchmarks aren't expected to panic, so we run them all in-process.
-            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
-                (benchfn.clone())(harness)
-            });
+            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, benchfn);
         }
         DynTestFn(f) => {
             match strategy {
@@ -553,7 +552,7 @@
         Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time),
     };
     let stdout = data.lock().unwrap().to_vec();
-    let message = CompletedTest::new(desc.clone(), test_result, exec_time, stdout);
+    let message = CompletedTest::new(desc, test_result, exec_time, stdout);
     monitor_ch.send(message).unwrap();
 }
 
@@ -602,7 +601,7 @@
         (result, test_output, exec_time)
     })();
 
-    let message = CompletedTest::new(desc.clone(), result, exec_time, test_output);
+    let message = CompletedTest::new(desc, result, exec_time, test_output);
     monitor_ch.send(message).unwrap();
 }
 
diff --git a/src/llvm-project b/src/llvm-project
index 9330ec5..a56b846 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 9330ec5a4c1df5fc1fa62f993ed6a04da68cb040
+Subproject commit a56b846ec7c96d8dc86418819baee40d70c92974
diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml
index 86a93d7..5e0f167 100644
--- a/src/rustc/Cargo.toml
+++ b/src/rustc/Cargo.toml
@@ -9,7 +9,6 @@
 path = "rustc.rs"
 
 [dependencies]
-rustc_target = { path = "../librustc_target" }
 rustc_driver = { path = "../librustc_driver" }
 
 # Make sure rustc_codegen_ssa ends up in the sysroot, because this
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index dd0111d..678d787 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -89,7 +89,11 @@
 extern "C" LLVMRustArchiveIteratorRef
 LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
   Archive *Archive = RustArchive->getBinary();
+#if LLVM_VERSION_GE(10, 0)
+  std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success());
+#else
   std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success());
+#endif
   auto Cur = Archive->child_begin(*Err);
   if (*Err) {
     LLVMRustSetLastError(toString(std::move(*Err)).c_str());
diff --git a/src/rustllvm/Linker.cpp b/src/rustllvm/Linker.cpp
index 7916721..69176f9 100644
--- a/src/rustllvm/Linker.cpp
+++ b/src/rustllvm/Linker.cpp
@@ -18,8 +18,7 @@
 LLVMRustLinkerNew(LLVMModuleRef DstRef) {
   Module *Dst = unwrap(DstRef);
 
-  auto Ret = llvm::make_unique<RustLinker>(*Dst);
-  return Ret.release();
+  return new RustLinker(*Dst);
 }
 
 extern "C" void
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 6698e5d..eaa845a 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -8,6 +8,7 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/InitializePasses.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -532,6 +533,18 @@
   ObjectFile,
 };
 
+#if LLVM_VERSION_GE(10, 0)
+static CodeGenFileType fromRust(LLVMRustFileType Type) {
+  switch (Type) {
+  case LLVMRustFileType::AssemblyFile:
+    return CGFT_AssemblyFile;
+  case LLVMRustFileType::ObjectFile:
+    return CGFT_ObjectFile;
+  default:
+    report_fatal_error("Bad FileType.");
+  }
+}
+#else
 static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
   switch (Type) {
   case LLVMRustFileType::AssemblyFile:
@@ -542,6 +555,7 @@
     report_fatal_error("Bad FileType.");
   }
 }
+#endif
 
 extern "C" LLVMRustResult
 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
@@ -849,7 +863,11 @@
                           int num_modules,
                           const char **preserved_symbols,
                           int num_symbols) {
+#if LLVM_VERSION_GE(10, 0)
+  auto Ret = std::make_unique<LLVMRustThinLTOData>();
+#else
   auto Ret = llvm::make_unique<LLVMRustThinLTOData>();
+#endif
 
   // Load each module's summary and merge it into one combined index
   for (int i = 0; i < num_modules; i++) {
@@ -944,6 +962,15 @@
         ExportedGUIDs.insert(GUID);
     }
   }
+#if LLVM_VERSION_GE(10, 0)
+  auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) {
+    const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
+    return (ExportList != Ret->ExportLists.end() &&
+      ExportList->second.count(VI)) ||
+      ExportedGUIDs.count(VI.getGUID());
+  };
+  thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing);
+#else
   auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
     const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
     return (ExportList != Ret->ExportLists.end() &&
@@ -951,6 +978,7 @@
       ExportedGUIDs.count(GUID);
   };
   thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported);
+#endif
 
   return Ret.release();
 }
@@ -1081,7 +1109,11 @@
 
 extern "C" LLVMRustThinLTOBuffer*
 LLVMRustThinLTOBufferCreate(LLVMModuleRef M) {
+#if LLVM_VERSION_GE(10, 0)
+  auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
+#else
   auto Ret = llvm::make_unique<LLVMRustThinLTOBuffer>();
+#endif
   {
     raw_string_ostream OS(Ret->data);
     {
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 720928e..46e4670 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -496,9 +496,11 @@
   if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
     Result |= DINode::DIFlags::FlagAppleBlock;
   }
+#if LLVM_VERSION_LT(10, 0)
   if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
     Result |= DINode::DIFlags::FlagBlockByrefStruct;
   }
+#endif
   if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
     Result |= DINode::DIFlags::FlagVirtual;
   }
@@ -825,6 +827,9 @@
   llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
       unwrapDI<DIDescriptor>(Context), Name, LinkageName,
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
+#if LLVM_VERSION_GE(10, 0)
+      /* isDefined */ true,
+#endif
       InitExpr, unwrapDIPtr<MDNode>(Decl),
 #if LLVM_VERSION_GE(8, 0)
       /* templateParams */ nullptr,
@@ -998,11 +1003,19 @@
 
 extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
                                          const char **Ptr) {
+#if LLVM_VERSION_GE(10, 0)
+  auto NameOrErr = (*unwrap(SI))->getName();
+  if (!NameOrErr)
+    report_fatal_error(NameOrErr.takeError());
+  *Ptr = NameOrErr->data();
+  return NameOrErr->size();
+#else
   StringRef Ret;
   if (std::error_code EC = (*unwrap(SI))->getName(Ret))
     report_fatal_error(EC.message());
   *Ptr = Ret.data();
   return Ret.size();
+#endif
 }
 
 // LLVMArrayType function does not support 64-bit ElementCount
@@ -1253,20 +1266,34 @@
                                             LLVMValueRef Dst, unsigned DstAlign,
                                             LLVMValueRef Src, unsigned SrcAlign,
                                             LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
+  return wrap(unwrap(B)->CreateMemCpy(
+      unwrap(Dst), MaybeAlign(DstAlign),
+      unwrap(Src), MaybeAlign(SrcAlign),
+      unwrap(Size), IsVolatile));
+#else
   return wrap(unwrap(B)->CreateMemCpy(
       unwrap(Dst), DstAlign,
       unwrap(Src), SrcAlign,
       unwrap(Size), IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
                                              LLVMValueRef Dst, unsigned DstAlign,
                                              LLVMValueRef Src, unsigned SrcAlign,
                                              LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(10, 0)
+  return wrap(unwrap(B)->CreateMemMove(
+      unwrap(Dst), MaybeAlign(DstAlign),
+      unwrap(Src), MaybeAlign(SrcAlign),
+      unwrap(Size), IsVolatile));
+#else
   return wrap(unwrap(B)->CreateMemMove(
       unwrap(Dst), DstAlign,
       unwrap(Src), SrcAlign,
       unwrap(Size), IsVolatile));
+#endif
 }
 
 extern "C" LLVMValueRef
@@ -1450,7 +1477,11 @@
 
 extern "C" LLVMRustModuleBuffer*
 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
+#if LLVM_VERSION_GE(10, 0)
+  auto Ret = std::make_unique<LLVMRustModuleBuffer>();
+#else
   auto Ret = llvm::make_unique<LLVMRustModuleBuffer>();
+#endif
   {
     raw_string_ostream OS(Ret->data);
     {
diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
index d5ddfb5..27fb3cb 100644
--- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
+++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -4,7 +4,7 @@
 
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal]
 struct StructWithDtor(u32);
 
 impl Drop for StructWithDtor {
@@ -16,7 +16,7 @@
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal]
     let x = [StructWithDtor(0), StructWithDtor(1)];
 
     drop_slice_in_place(&x);
@@ -31,7 +31,6 @@
         // not have drop-glue for the unsized [StructWithDtor]. This has to be
         // generated though when the drop_in_place() intrinsic is used.
         //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal]
-        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal]
         ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]);
     }
 }
diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs
index 94e79f0..675bdfd 100644
--- a/src/test/codegen-units/item-collection/generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs
@@ -37,7 +37,7 @@
 struct NonGenericNoDrop(i32);
 
 struct NonGenericWithDrop(i32);
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal]
 
 impl Drop for NonGenericWithDrop {
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0]
@@ -47,11 +47,11 @@
 //~ MONO_ITEM fn generic_drop_glue::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
     let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
     let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y;
 
@@ -60,17 +60,17 @@
 
     // This is supposed to generate drop-glue because it contains a field that
     // needs to be dropped.
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal]
     let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y;
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<i32, i64>
     let _ = match EnumWithDrop::A::<i32, i64>(0) {
         EnumWithDrop::A(x) => x,
         EnumWithDrop::B(x) => x as i32
     };
 
-    //~MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal]
+    //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<f64, f32>
     let _ = match EnumWithDrop::B::<f64, f32>(1.0) {
         EnumWithDrop::A(x) => x,
diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
index e79b069..db0390b 100644
--- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
+++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
@@ -24,13 +24,13 @@
 fn start(_: isize, _: *const *const u8) -> isize {
     let s1 = Struct { _a: 0u32 };
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal]
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u32>
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u32>
     let _ = &s1 as &Trait;
 
     let s1 = Struct { _a: 0u64 };
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal]
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
     let _ = &s1 as &Trait;
diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
index f13952b..a899b8b 100644
--- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
@@ -5,7 +5,7 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
 struct StructWithDrop {
     x: i32
 }
@@ -19,7 +19,7 @@
     x: i32
 }
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
 enum EnumWithDrop {
     A(i32)
 }
diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
index 14545a3..7e29af4 100644
--- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
@@ -5,11 +5,11 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Root(Intermediate);
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Intermediate(Leaf);
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Leaf;
 
 impl Drop for Leaf {
@@ -30,15 +30,15 @@
 fn start(_: isize, _: *const *const u8) -> isize {
     let _ = Root(Intermediate(Leaf));
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<u32>
     let _ = RootGen(IntermediateGen(LeafGen(0u32)));
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
     let _ = RootGen(IntermediateGen(LeafGen(0i16)));
 
diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
index 54aff57..d77de53 100644
--- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
@@ -5,7 +5,7 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal]
 struct Dropped;
 
 impl Drop for Dropped {
@@ -16,11 +16,11 @@
 //~ MONO_ITEM fn tuple_drop_glue::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal]
     let x = (0u32, Dropped);
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal]
     let x = (0i16, (Dropped, true));
 
     0
diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs
index fd794df..1ed60dc 100644
--- a/src/test/codegen-units/item-collection/unsizing.rs
+++ b/src/test/codegen-units/item-collection/unsizing.rs
@@ -48,13 +48,13 @@
 fn start(_: isize, _: *const *const u8) -> isize {
     // simple case
     let bool_sized = &true;
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0]
     let _bool_unsized = bool_sized as &Trait;
 
     let char_sized = &'a';
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<char> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<char> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0]
     let _char_unsized = char_sized as &Trait;
 
@@ -64,13 +64,13 @@
         _b: 2,
         _c: 3.0f64
     };
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0]
     let _struct_unsized = struct_sized as &Struct<Trait>;
 
     // custom coercion
     let wrapper_sized = Wrapper(&0u32);
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0]
     let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
 
diff --git a/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
index 9050e8f..ffbd0dc 100644
--- a/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
+++ b/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
@@ -1,4 +1,6 @@
-// compile-flags:-Zshare-generics=yes
+// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
+//       prevent drop-glue from participating in share-generics.
+// compile-flags:-Zshare-generics=yes -Copt-level=0
 // no-prefer-dynamic
 
 #![crate_type="rlib"]
@@ -8,5 +10,17 @@
 }
 
 pub fn use_generic_fn_f32() -> (f32, f32) {
+    // This line causes drop glue for Foo to be instantiated. We want to make
+    // sure that this crate exports an instance to be re-used by share-generics.
+    let _ = Foo(0);
+
     generic_fn(0.0f32, 1.0f32)
 }
+
+pub struct Foo(pub u32);
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("foo");
+    }
+}
diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs
index 0f3d72d..f85ae0c 100644
--- a/src/test/codegen-units/partitioning/extern-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs
@@ -11,14 +11,14 @@
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
 //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
 pub fn user()
 {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
@@ -30,7 +30,7 @@
     //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
     pub fn user()
     {
-        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
     }
 }
diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs
index 938d4ffb..366af4d 100644
--- a/src/test/codegen-units/partitioning/local-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/local-drop-glue.rs
@@ -7,7 +7,7 @@
 #![allow(dead_code)]
 #![crate_type="rlib"]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
 struct Struct {
     _a: u32
 }
@@ -17,7 +17,7 @@
     fn drop(&mut self) {}
 }
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
 struct Outer {
     _a: Struct
 }
@@ -36,10 +36,10 @@
 {
     use super::Struct;
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
     struct Struct2 {
         _a: Struct,
-        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
         _b: (u32, Struct),
     }
 
diff --git a/src/test/codegen-units/partitioning/shared-generics.rs b/src/test/codegen-units/partitioning/shared-generics.rs
index 58e485b..47ff944 100644
--- a/src/test/codegen-units/partitioning/shared-generics.rs
+++ b/src/test/codegen-units/partitioning/shared-generics.rs
@@ -1,6 +1,8 @@
 // ignore-tidy-linelength
 // no-prefer-dynamic
-// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe
+// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
+//       prevent drop-glue from participating in share-generics.
+// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe -Copt-level=0
 
 #![crate_type="rlib"]
 
@@ -16,6 +18,10 @@
     // This should not generate a monomorphization because it's already
     // available in `shared_generics_aux`.
     let _ = shared_generics_aux::generic_fn(0.0f32, 3.0f32);
-}
 
-// MONO_ITEM drop-glue i8
+    // The following line will drop an instance of `Foo`, generating a call to
+    // Foo's drop-glue function. However, share-generics should take care of
+    // reusing the drop-glue from the upstream crate, so we do not expect a
+    // mono item for the drop-glue
+    let _ = shared_generics_aux::Foo(1);
+}
diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs
index 5d23a4e..06e2ef6 100644
--- a/src/test/codegen-units/partitioning/vtable-through-const.rs
+++ b/src/test/codegen-units/partitioning/vtable-through-const.rs
@@ -66,7 +66,7 @@
 //~ MONO_ITEM fn vtable_through_const::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ vtable_through_const[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
 
     // Since Trait1::do_something() is instantiated via its default implementation,
     // it is considered a generic and is instantiated here only because it is
diff --git a/src/test/codegen/abi-main-signature-32bit-c-int.rs b/src/test/codegen/abi-main-signature-32bit-c-int.rs
index c7aab09..a7a4520 100644
--- a/src/test/codegen/abi-main-signature-32bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-32bit-c-int.rs
@@ -7,4 +7,4 @@
 fn main() {
 }
 
-// CHECK: define i32 @main(i32, i8**)
+// CHECK: define i32 @main(i32{{( %0)?}}, i8**{{( %1)?}})
diff --git a/src/test/codegen/bool-cmp.rs b/src/test/codegen/bool-cmp.rs
index 8769a4c..5090f7c 100644
--- a/src/test/codegen/bool-cmp.rs
+++ b/src/test/codegen/bool-cmp.rs
@@ -10,8 +10,9 @@
 // CHECK-LABEL: @cmp_bool
 #[no_mangle]
 pub fn cmp_bool(a: bool, b: bool) -> Ordering {
+// LLVM 10 produces (zext a) + (sext b), but the final lowering is (zext a) - (zext b).
 // CHECK: zext i1
-// CHECK: zext i1
-// CHECK: sub nsw
+// CHECK: {{z|s}}ext i1
+// CHECK: {{sub|add}} nsw
     a.cmp(&b)
 }
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index 7d65ad1..a89ecdf 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -14,10 +14,9 @@
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}},
 
 #[derive(Copy, Clone)]
-
 // repr(i16) is required for the {low,high}_align_const test
 #[repr(i16)]
 pub enum E<A, B> {
@@ -31,7 +30,7 @@
 // CHECK-LABEL: @static_enum_const
 #[no_mangle]
 pub fn static_enum_const() -> E<i16, i32> {
-   STATIC
+    STATIC
 }
 
 // CHECK-LABEL: @inline_enum_const
@@ -43,15 +42,15 @@
 // CHECK-LABEL: @low_align_const
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
-// Check that low_align_const and high_align_const use the same constant
-// CHECK: i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
+    // Check that low_align_const and high_align_const use the same constant
+    // CHECK: load %"E<i16, [i16; 3]>"*, %"E<i16, [i16; 3]>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, [i16; 3]>"**),
     *&E::A(0)
 }
 
 // CHECK-LABEL: @high_align_const
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
-// Check that low_align_const and high_align_const use the same constant
-// CHECK: i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
+    // Check that low_align_const and high_align_const use the same constant
+    // CHECK: load %"E<i16, i32>"*, %"E<i16, i32>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, i32>"**),
     *&E::A(0)
 }
diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs
index 959929f..0c7f3bb 100644
--- a/src/test/codegen/drop.rs
+++ b/src/test/codegen/drop.rs
@@ -21,7 +21,7 @@
 // regular function exit. We used to have problems with quadratic growths of drop calls in such
 // functions.
 // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the
-// comment, that's `; call core::ptr::real_drop_in_place::<drop::SomeUniqueName>`
+// comment, that's `; call core::intrinsics::drop_in_place::<drop::SomeUniqueName>`
 // for the `v0` mangling, should switch to matching on that once `legacy` is gone.
 // CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index 5c9aa48..3511c7c 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -73,7 +73,7 @@
   x
 }
 
-// CHECK: @struct_return(%S* noalias nocapture sret dereferenceable(32))
+// CHECK: @struct_return(%S* noalias nocapture sret dereferenceable(32){{( %0)?}})
 #[no_mangle]
 pub fn struct_return() -> S {
   S {
@@ -117,7 +117,7 @@
 pub fn trait_borrow(_: &Drop) {
 }
 
-// CHECK: @trait_box({}* noalias nonnull align 1, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}))
+// CHECK: @trait_box({}* noalias nonnull align 1{{( %0)?}}, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
 #[no_mangle]
 pub fn trait_box(_: Box<Drop>) {
 }
diff --git a/src/test/codegen/intrinsics/prefetch.rs b/src/test/codegen/intrinsics/prefetch.rs
index 4cd38e1..2386fc4 100644
--- a/src/test/codegen/intrinsics/prefetch.rs
+++ b/src/test/codegen/intrinsics/prefetch.rs
@@ -9,13 +9,13 @@
 #[no_mangle]
 pub fn check_prefetch_read_data(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 0, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 0, i32 1)
         prefetch_read_data(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 1, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 1, i32 1)
         prefetch_read_data(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 2, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 2, i32 1)
         prefetch_read_data(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 3, i32 1)
         prefetch_read_data(data.as_ptr(), 3);
     }
 }
@@ -23,13 +23,13 @@
 #[no_mangle]
 pub fn check_prefetch_write_data(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 0, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 0, i32 1)
         prefetch_write_data(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 1, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 1, i32 1)
         prefetch_write_data(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 2, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 2, i32 1)
         prefetch_write_data(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 1)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 3, i32 1)
         prefetch_write_data(data.as_ptr(), 3);
     }
 }
@@ -37,13 +37,13 @@
 #[no_mangle]
 pub fn check_prefetch_read_instruction(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 0, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 0, i32 0)
         prefetch_read_instruction(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 1, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 1, i32 0)
         prefetch_read_instruction(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 2, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 2, i32 0)
         prefetch_read_instruction(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 0, i32 3, i32 0)
         prefetch_read_instruction(data.as_ptr(), 3);
     }
 }
@@ -51,13 +51,13 @@
 #[no_mangle]
 pub fn check_prefetch_write_instruction(data: &[i8]) {
     unsafe {
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 0, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 0, i32 0)
         prefetch_write_instruction(data.as_ptr(), 0);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 1, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 1, i32 0)
         prefetch_write_instruction(data.as_ptr(), 1);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 2, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 2, i32 0)
         prefetch_write_instruction(data.as_ptr(), 2);
-        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 0)
+        // CHECK: call void @llvm.prefetch{{.*}}(i8* %{{.*}}, i32 1, i32 3, i32 0)
         prefetch_write_instruction(data.as_ptr(), 3);
     }
 }
diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs
index 2050193..5050ed1 100644
--- a/src/test/codegen/naked-functions.rs
+++ b/src/test/codegen/naked-functions.rs
@@ -17,7 +17,7 @@
 // CHECK: Function Attrs: naked
 #[no_mangle]
 #[naked]
-// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+}})
+// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
 pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: %a = alloca i{{[0-9]+}}
@@ -36,7 +36,7 @@
 }
 
 // CHECK: Function Attrs: naked
-// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %0)?}})
 #[no_mangle]
 #[naked]
 pub fn naked_with_args_and_return(a: isize) -> isize {
diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs
index 99f3464..8fbe712 100644
--- a/src/test/codegen/repeat-trusted-len.rs
+++ b/src/test/codegen/repeat-trusted-len.rs
@@ -13,6 +13,6 @@
 // CHECK-LABEL: @repeat_take_collect
 #[no_mangle]
 pub fn repeat_take_collect() -> Vec<u8> {
-// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
+// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
     iter::repeat(42).take(100000).collect()
 }
diff --git a/src/test/codegen/repr-transparent-sysv64.rs b/src/test/codegen/repr-transparent-sysv64.rs
index b71cb14..886b0dd 100644
--- a/src/test/codegen/repr-transparent-sysv64.rs
+++ b/src/test/codegen/repr-transparent-sysv64.rs
@@ -10,7 +10,7 @@
 #[repr(transparent)]
 pub struct Rgb8Wrap(Rgb8);
 
-// CHECK: i24 @test_Rgb8Wrap(i24)
+// CHECK: i24 @test_Rgb8Wrap(i24{{( %0)?}})
 #[no_mangle]
 pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }
 
@@ -23,6 +23,6 @@
 #[repr(transparent)]
 pub struct SmallUnion(FloatBits);
 
-// CHECK: i32 @test_SmallUnion(i32)
+// CHECK: i32 @test_SmallUnion(i32{{( %0)?}})
 #[no_mangle]
 pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }
diff --git a/src/test/codegen/sanitizer-memory-track-orgins.rs b/src/test/codegen/sanitizer-memory-track-orgins.rs
index fd8be0b..1fd496b 100644
--- a/src/test/codegen/sanitizer-memory-track-orgins.rs
+++ b/src/test/codegen/sanitizer-memory-track-orgins.rs
@@ -4,17 +4,21 @@
 // needs-sanitizer-support
 // only-linux
 // only-x86_64
-// revisions:MSAN-0 MSAN-1 MSAN-2
+// revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO
 //
 //[MSAN-0] compile-flags: -Zsanitizer=memory
 //[MSAN-1] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1
 //[MSAN-2] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins
+//[MSAN-1-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins=1 -C lto=fat
+//[MSAN-2-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-memory-track-origins -C lto=fat
 
 #![crate_type="lib"]
 
 // MSAN-0-NOT: @__msan_track_origins
 // MSAN-1:     @__msan_track_origins = weak_odr local_unnamed_addr constant i32 1
 // MSAN-2:     @__msan_track_origins = weak_odr local_unnamed_addr constant i32 2
+// MSAN-1-LTO: @__msan_track_origins = weak_odr local_unnamed_addr constant i32 1
+// MSAN-2-LTO: @__msan_track_origins = weak_odr local_unnamed_addr constant i32 2
 //
 // MSAN-0-LABEL: define void @copy(
 // MSAN-1-LABEL: define void @copy(
diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs
index a292332..9a583725 100644
--- a/src/test/codegen/sanitizer-recover.rs
+++ b/src/test/codegen/sanitizer-recover.rs
@@ -4,31 +4,47 @@
 // needs-sanitizer-support
 // only-linux
 // only-x86_64
-// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER
+// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO
+// no-prefer-dynamic
 //
-//[ASAN]         compile-flags: -Zsanitizer=address
-//[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address
-//[MSAN]         compile-flags: -Zsanitizer=memory
-//[MSAN-RECOVER] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory
+//[ASAN]             compile-flags: -Zsanitizer=address
+//[ASAN-RECOVER]     compile-flags: -Zsanitizer=address -Zsanitizer-recover=address
+//[MSAN]             compile-flags: -Zsanitizer=memory
+//[MSAN-RECOVER]     compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory
+//[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory -C lto=fat
+//
+// MSAN-NOT:         @__msan_keep_going
+// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}} constant i32 1
+// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}} constant i32 1
 
-#![crate_type="lib"]
-
-// ASAN-LABEL:         define i32 @penguin(
+// ASAN-LABEL: define i32 @penguin(
+// ASAN:         call void @__asan_report_load4(i64 %0)
+// ASAN:         unreachable
+// ASAN:       }
+//
 // ASAN-RECOVER-LABEL: define i32 @penguin(
-// MSAN-LABEL:         define i32 @penguin(
+// ASAN-RECOVER:         call void @__asan_report_load4_noabort(
+// ASAN-RECOVER-NOT:     unreachable
+// ASAN:               }
+//
+// MSAN-LABEL: define i32 @penguin(
+// MSAN:         call void @__msan_warning_noreturn()
+// MSAN:         unreachable
+// MSAN:       }
+//
 // MSAN-RECOVER-LABEL: define i32 @penguin(
+// MSAN-RECOVER:         call void @__msan_warning()
+// MSAN-RECOVER-NOT:     unreachable
+// MSAN-RECOVER:       }
+//
+// MSAN-RECOVER-LTO-LABEL: define i32 @penguin(
+// MSAN-RECOVER-LTO:          call void @__msan_warning()
+// MSAN-RECOVER-LTO-NOT:      unreachable
+// MSAN-RECOVER-LTO:       }
+//
 #[no_mangle]
 pub fn penguin(p: &mut i32) -> i32 {
-    // ASAN:             call void @__asan_report_load4(i64 %0)
-    // ASAN:             unreachable
-    //
-    // ASAN-RECOVER:     call void @__asan_report_load4_noabort(
-    // ASAN-RECOVER-NOT: unreachable
-    //
-    // MSAN:             call void @__msan_warning_noreturn()
-    // MSAN:             unreachable
-    //
-    // MSAN-RECOVER:     call void @__msan_warning()
-    // MSAN-RECOVER-NOT: unreachable
     *p
 }
+
+fn main() {}
diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs
index 98a9ff9..afea01e 100644
--- a/src/test/codegen/union-abi.rs
+++ b/src/test/codegen/union-abi.rs
@@ -54,7 +54,7 @@
 
 pub union UnionF32U32{a:f32, b:u32}
 
-// CHECK: define i32 @test_UnionF32U32(i32)
+// CHECK: define i32 @test_UnionF32U32(i32{{( %0)?}})
 #[no_mangle]
 pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
 
diff --git a/src/test/compile-fail/consts/const-fn-error.rs b/src/test/compile-fail/consts/const-fn-error.rs
index 5d26059..9db595a 100644
--- a/src/test/compile-fail/consts/const-fn-error.rs
+++ b/src/test/compile-fail/consts/const-fn-error.rs
@@ -6,6 +6,7 @@
     let mut sum = 0;
     for i in 0..x {
         //~^ ERROR E0015
+        //~| ERROR E0015
         //~| ERROR E0658
         //~| ERROR E0080
         //~| ERROR E0744
diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs
index ee37aaa..597fbbf 100644
--- a/src/test/compile-fail/issue-52443.rs
+++ b/src/test/compile-fail/issue-52443.rs
@@ -8,6 +8,7 @@
     //~| WARN denote infinite loops with
     [(); { for _ in 0usize.. {}; 0}];
     //~^ ERROR calls in constants are limited to constant functions
+    //~| ERROR calls in constants are limited to constant functions
     //~| ERROR `for` is not allowed in a `const`
     //~| ERROR references in constants may only refer to immutable values
     //~| ERROR evaluation of constant value failed
diff --git a/src/test/compile-fail/panic-handler-twice.rs b/src/test/compile-fail/panic-handler-twice.rs
index c0f2c51..0c5359b 100644
--- a/src/test/compile-fail/panic-handler-twice.rs
+++ b/src/test/compile-fail/panic-handler-twice.rs
@@ -10,7 +10,7 @@
 
 #[panic_handler]
 fn panic(info: &PanicInfo) -> ! {
-    //~^ error duplicate lang item found: `panic_impl`
+    //~^ ERROR found duplicate lang item `panic_impl`
     loop {}
 }
 
diff --git a/src/test/debuginfo/borrowed-enum-legacy.rs b/src/test/debuginfo/borrowed-enum-legacy.rs
deleted file mode 100644
index 9a973ed..0000000
--- a/src/test/debuginfo/borrowed-enum-legacy.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:print *the_a_ref
-// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, [...]}}
-// gdbr-check:$1 = borrowed_enum_legacy::ABC::TheA{x: 0, y: 8970181431921507452}
-
-// gdb-command:print *the_b_ref
-// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, [...]}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}}
-// gdbr-check:$2 = borrowed_enum_legacy::ABC::TheB(0, 286331153, 286331153)
-
-// gdb-command:print *univariant_ref
-// gdbg-check:$3 = {{__0 = 4820353753753434}}
-// gdbr-check:$3 = borrowed_enum_legacy::Univariant::TheOnlyCase(4820353753753434)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print *the_a_ref
-// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
-// lldbr-check:(borrowed_enum_legacy::ABC::TheA) *the_a_ref = TheA { borrowed_enum_legacy::ABC::TheA: 0, borrowed_enum_legacy::ABC::TheB: 8970181431921507452 }
-// lldb-command:print *the_b_ref
-// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
-// lldbr-check:(borrowed_enum_legacy::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 }
-// lldb-command:print *univariant_ref
-// lldbg-check:[...]$2 = TheOnlyCase(4820353753753434)
-// lldbr-check:(borrowed_enum_legacy::Univariant) *univariant_ref = { borrowed_enum_legacy::TheOnlyCase = { = 4820353753753434 } }
-
-#![allow(unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
-    TheA { x: i64, y: i64 },
-    TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
-    TheOnlyCase(i64)
-}
-
-fn main() {
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let the_a = ABC::TheA { x: 0, y: 8970181431921507452 };
-    let the_a_ref: &ABC = &the_a;
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let the_b = ABC::TheB (0, 286331153, 286331153);
-    let the_b_ref: &ABC = &the_b;
-
-    let univariant = Univariant::TheOnlyCase(4820353753753434);
-    let univariant_ref: &Univariant = &univariant;
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes-legacy.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes-legacy.rs
deleted file mode 100644
index 4f17e48..0000000
--- a/src/test/debuginfo/generic-enum-with-different-disr-sizes-legacy.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// ignore-tidy-linelength
-// ignore-lldb: FIXME(#27089)
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-// gdb-command:run
-
-// gdb-command:print eight_bytes1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}}
-// gdbr-check:$1 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(100)
-
-// gdb-command:print four_bytes1
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}}
-// gdbr-check:$2 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(101)
-
-// gdb-command:print two_bytes1
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}}
-// gdbr-check:$3 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(102)
-
-// gdb-command:print one_byte1
-// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}}
-// gdbr-check:$4 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant1(65)
-
-
-// gdb-command:print eight_bytes2
-// gdbg-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}}
-// gdbr-check:$5 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(100)
-
-// gdb-command:print four_bytes2
-// gdbg-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}}
-// gdbr-check:$6 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(101)
-
-// gdb-command:print two_bytes2
-// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}}
-// gdbr-check:$7 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(102)
-
-// gdb-command:print one_byte2
-// gdbg-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}}
-// gdbr-check:$8 = generic_enum_with_different_disr_sizes_legacy::Enum::Variant2(65)
-
-// gdb-command:continue
-
-// === LLDB TESTS ==================================================================================
-// lldb-command:run
-
-// lldb-command:print eight_bytes1
-// lldb-check:[...]$0 = Variant1(100)
-// lldb-command:print four_bytes1
-// lldb-check:[...]$1 = Variant1(101)
-// lldb-command:print two_bytes1
-// lldb-check:[...]$2 = Variant1(102)
-// lldb-command:print one_byte1
-// lldb-check:[...]$3 = Variant1('A')
-
-// lldb-command:print eight_bytes2
-// lldb-check:[...]$4 = Variant2(100)
-// lldb-command:print four_bytes2
-// lldb-check:[...]$5 = Variant2(101)
-// lldb-command:print two_bytes2
-// lldb-check:[...]$6 = Variant2(102)
-// lldb-command:print one_byte2
-// lldb-check:[...]$7 = Variant2('A')
-
-// lldb-command:continue
-
-#![allow(unused_variables)]
-#![allow(dead_code)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-// This test case makes sure that we get correct type descriptions for the enum
-// discriminant of different instantiations of the same generic enum type where,
-// dependending on the generic type parameter(s), the discriminant has a
-// different size in memory.
-
-enum Enum<T> {
-    Variant1(T),
-    Variant2(T)
-}
-
-fn main() {
-    // These are ordered for descending size on purpose
-    let eight_bytes1 = Enum::Variant1(100.0f64);
-    let four_bytes1 = Enum::Variant1(101i32);
-    let two_bytes1 = Enum::Variant1(102i16);
-    let one_byte1 = Enum::Variant1(65u8);
-
-    let eight_bytes2 = Enum::Variant2(100.0f64);
-    let four_bytes2 = Enum::Variant2(101i32);
-    let two_bytes2 = Enum::Variant2(102i16);
-    let one_byte2 = Enum::Variant2(65u8);
-
-    zzz(); // #break
-}
-
-fn zzz() { () }
diff --git a/src/test/debuginfo/generic-struct-style-enum-legacy.rs b/src/test/debuginfo/generic-struct-style-enum-legacy.rs
deleted file mode 100644
index 37a875a..0000000
--- a/src/test/debuginfo/generic-struct-style-enum-legacy.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12.9
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = generic_struct_style_enum_legacy::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868}
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = generic_struct_style_enum_legacy::Regular::Case2{a: 0, b: 286331153, c: 286331153}
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}}
-// gdbr-check:$3 = generic_struct_style_enum_legacy::Regular::Case3{a: 0, b: 6438275382588823897}
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{a = -1}}
-// gdbr-check:$4 = generic_struct_style_enum_legacy::Univariant<i32>::TheOnlyCase{a: -1}
-
-
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
-// substituted with something of size `xx` bits and the same alignment as an integer type of the
-// same size.
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular<T16, T32, T64> {
-    Case1 { a: T64, b: T16, c: T16, d: T16, e: T16},
-    Case2 { a: T64, b: T32, c: T32},
-    Case3 { a: T64, b: T64 }
-}
-
-enum Univariant<T> {
-    TheOnlyCase { a: T }
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1: Regular<u16, u32, i64> = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2: Regular<i16, u32, i64>  = Case2 { a: 0, b: 286331153, c: 286331153 };
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3: Regular<u16, i32, u64>  = Case3 { a: 0, b: 6438275382588823897 };
-
-    let univariant = TheOnlyCase { a: -1 };
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/generic-tuple-style-enum-legacy.rs b/src/test/debuginfo/generic-tuple-style-enum-legacy.rs
deleted file mode 100644
index 452e900..0000000
--- a/src/test/debuginfo/generic-tuple-style-enum-legacy.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-// ignore-gdb-version: 7.11.90 - 7.12.9
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = generic_tuple_style_enum_legacy::Regular::Case1(0, 31868, 31868, 31868, 31868)
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = generic_tuple_style_enum_legacy::Regular::Case2(0, 286331153, 286331153)
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}}
-// gdbr-check:$3 = generic_tuple_style_enum_legacy::Regular::Case3(0, 6438275382588823897)
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{__0 = -1}}
-// gdbr-check:$4 = generic_tuple_style_enum_legacy::Univariant<i64>::TheOnlyCase(-1)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print case1
-// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
-// lldbr-check:(generic_tuple_style_enum_legacy::Regular<u16, u32, u64>::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
-
-// lldb-command:print case2
-// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
-// lldbr-check:(generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case2) case2 = Regular<i16, i32, i64>::Case2 { generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case2: 286331153, generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case3: 286331153 }
-
-// lldb-command:print case3
-// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
-// lldbr-check:(generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case3) case3 = Regular<i16, i32, i64>::Case3 { generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case1: 0, generic_tuple_style_enum_legacy::Regular<i16, i32, i64>::Case2: 6438275382588823897 }
-
-// lldb-command:print univariant
-// lldbg-check:[...]$3 = TheOnlyCase(-1)
-// lldbr-check:(generic_tuple_style_enum_legacy::Univariant<i64>) univariant = { generic_tuple_style_enum_legacy::TheOnlyCase = { = -1 } }
-
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
-// substituted with something of size `xx` bits and the same alignment as an integer type of the
-// same size.
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular<T16, T32, T64> {
-    Case1(T64, T16, T16, T16, T16),
-    Case2(T64, T32, T32),
-    Case3(T64, T64)
-}
-
-enum Univariant<T64> {
-    TheOnlyCase(T64)
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1: Regular<u16, u32, u64> = Case1(0_u64, 31868_u16, 31868_u16, 31868_u16, 31868_u16);
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2: Regular<i16, i32, i64> = Case2(0_i64, 286331153_i32, 286331153_i32);
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3: Regular<i16, i32, i64> = Case3(0_i64, 6438275382588823897_i64);
-
-    let univariant = TheOnlyCase(-1_i64);
-
-    zzz(); // #break
-}
-
-fn zzz() { () }
diff --git a/src/test/debuginfo/recursive-struct-legacy.rs b/src/test/debuginfo/recursive-struct-legacy.rs
deleted file mode 100644
index 9928670..0000000
--- a/src/test/debuginfo/recursive-struct-legacy.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-// ignore-tidy-linelength
-// ignore-lldb
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// gdb-command:run
-
-// gdb-command:print stack_unique.value
-// gdb-check:$1 = 0
-// gdbg-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print stack_unique.next.val.value
-// gdb-check:$2 = 1
-
-// gdbg-command:print unique_unique->value
-// gdbr-command:print unique_unique.value
-// gdb-check:$3 = 2
-// gdbg-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print unique_unique.next.val.value
-// gdb-check:$4 = 3
-
-// gdb-command:print vec_unique[0].value
-// gdb-check:$5 = 6.5
-// gdbg-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print vec_unique[0].next.val.value
-// gdb-check:$6 = 7.5
-
-// gdbg-command:print borrowed_unique->value
-// gdbr-command:print borrowed_unique.value
-// gdb-check:$7 = 8.5
-// gdbg-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value
-// gdbr-command:print borrowed_unique.next.val.value
-// gdb-check:$8 = 9.5
-
-// LONG CYCLE
-// gdb-command:print long_cycle1.value
-// gdb-check:$9 = 20
-// gdbg-command:print long_cycle1.next->value
-// gdbr-command:print long_cycle1.next.value
-// gdb-check:$10 = 21
-// gdbg-command:print long_cycle1.next->next->value
-// gdbr-command:print long_cycle1.next.next.value
-// gdb-check:$11 = 22
-// gdbg-command:print long_cycle1.next->next->next->value
-// gdbr-command:print long_cycle1.next.next.next.value
-// gdb-check:$12 = 23
-
-// gdb-command:print long_cycle2.value
-// gdb-check:$13 = 24
-// gdbg-command:print long_cycle2.next->value
-// gdbr-command:print long_cycle2.next.value
-// gdb-check:$14 = 25
-// gdbg-command:print long_cycle2.next->next->value
-// gdbr-command:print long_cycle2.next.next.value
-// gdb-check:$15 = 26
-
-// gdb-command:print long_cycle3.value
-// gdb-check:$16 = 27
-// gdbg-command:print long_cycle3.next->value
-// gdbr-command:print long_cycle3.next.value
-// gdb-check:$17 = 28
-
-// gdb-command:print long_cycle4.value
-// gdb-check:$18 = 29.5
-
-// gdbg-command:print (*****long_cycle_w_anonymous_types).value
-// gdbr-command:print long_cycle_w_anonymous_types.value
-// gdb-check:$19 = 30
-
-// gdbg-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value
-// gdbr-command:print long_cycle_w_anonymous_types.next.val.value
-// gdb-check:$20 = 31
-
-// gdb-command:continue
-
-#![allow(unused_variables)]
-#![feature(box_syntax)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Opt::{Empty, Val};
-
-enum Opt<T> {
-    Empty,
-    Val { val: T }
-}
-
-struct UniqueNode<T> {
-    next: Opt<Box<UniqueNode<T>>>,
-    value: T
-}
-
-struct LongCycle1<T> {
-    next: Box<LongCycle2<T>>,
-    value: T,
-}
-
-struct LongCycle2<T> {
-    next: Box<LongCycle3<T>>,
-    value: T,
-}
-
-struct LongCycle3<T> {
-    next: Box<LongCycle4<T>>,
-    value: T,
-}
-
-struct LongCycle4<T> {
-    next: Option<Box<LongCycle1<T>>>,
-    value: T,
-}
-
-struct LongCycleWithAnonymousTypes {
-    next: Opt<Box<Box<Box<Box<Box<LongCycleWithAnonymousTypes>>>>>>,
-    value: usize,
-}
-
-// This test case makes sure that recursive structs are properly described. The Node structs are
-// generic so that we can have a new type (that newly needs to be described) for the different
-// cases. The potential problem with recursive types is that the DI generation algorithm gets
-// trapped in an endless loop. To make sure, we actually test this in the different cases, we have
-// to operate on a new type each time, otherwise we would just hit the DI cache for all but the
-// first case.
-
-// The different cases below (stack_*, unique_*, box_*, etc) are set up so that the type description
-// algorithm will enter the type reference cycle that is created by a recursive definition from a
-// different context each time.
-
-// The "long cycle" cases are constructed to span a longer, indirect recursion cycle between types.
-// The different locals will cause the DI algorithm to enter the type reference cycle at different
-// points.
-
-fn main() {
-    let stack_unique: UniqueNode<u16> = UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 1,
-            }
-        },
-        value: 0,
-    };
-
-    let unique_unique: Box<UniqueNode<u32>> = box UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 3,
-            }
-        },
-        value: 2,
-    };
-
-    let vec_unique: [UniqueNode<f32>; 1] = [UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 7.5,
-            }
-        },
-        value: 6.5,
-    }];
-
-    let borrowed_unique: &UniqueNode<f64> = &UniqueNode {
-        next: Val {
-            val: box UniqueNode {
-                next: Empty,
-                value: 9.5,
-            }
-        },
-        value: 8.5,
-    };
-
-    // LONG CYCLE
-    let long_cycle1: LongCycle1<u16> = LongCycle1 {
-        next: box LongCycle2 {
-            next: box LongCycle3 {
-                next: box LongCycle4 {
-                    next: None,
-                    value: 23,
-                },
-                value: 22,
-            },
-            value: 21
-        },
-        value: 20
-    };
-
-    let long_cycle2: LongCycle2<u32> = LongCycle2 {
-        next: box LongCycle3 {
-            next: box LongCycle4 {
-                next: None,
-                value: 26,
-            },
-            value: 25,
-        },
-        value: 24
-    };
-
-    let long_cycle3: LongCycle3<u64> = LongCycle3 {
-        next: box LongCycle4 {
-            next: None,
-            value: 28,
-        },
-        value: 27,
-    };
-
-    let long_cycle4: LongCycle4<f32> = LongCycle4 {
-        next: None,
-        value: 29.5,
-    };
-
-    // It's important that LongCycleWithAnonymousTypes is encountered only at the end of the
-    // `box` chain.
-    let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes {
-        next: Val {
-            val: box box box box box LongCycleWithAnonymousTypes {
-                next: Empty,
-                value: 31,
-            }
-        },
-        value: 30
-    };
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/struct-style-enum-legacy.rs b/src/test/debuginfo/struct-style-enum-legacy.rs
deleted file mode 100644
index 1433493..0000000
--- a/src/test/debuginfo/struct-style-enum-legacy.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = struct_style_enum_legacy::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868}
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = struct_style_enum_legacy::Regular::Case2{a: 0, b: 286331153, c: 286331153}
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}}
-// gdbr-check:$3 = struct_style_enum_legacy::Regular::Case3{a: 0, b: 6438275382588823897}
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{a = -1}}
-// gdbr-check:$4 = struct_style_enum_legacy::Univariant::TheOnlyCase{a: -1}
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print case1
-// lldbg-check:[...]$0 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }
-// lldbr-check:(struct_style_enum_legacy::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 }
-
-// lldb-command:print case2
-// lldbg-check:[...]$1 = Case2 { a: 0, b: 286331153, c: 286331153 }
-// lldbr-check:(struct_style_enum_legacy::Regular::Case2) case2 = Case2 { struct_style_enum_legacy::Regular::Case1: 0, struct_style_enum_legacy::Regular::Case2: 286331153, struct_style_enum_legacy::Regular::Case3: 286331153 }
-
-// lldb-command:print case3
-// lldbg-check:[...]$2 = Case3 { a: 0, b: 6438275382588823897 }
-// lldbr-check:(struct_style_enum_legacy::Regular::Case3) case3 = Case3 { struct_style_enum_legacy::Regular::Case1: 0, struct_style_enum_legacy::Regular::Case2: 6438275382588823897 }
-
-// lldb-command:print univariant
-// lldbg-check:[...]$3 = TheOnlyCase { a: -1 }
-// lldbr-check:(struct_style_enum_legacy::Univariant) univariant = Univariant { struct_style_enum_legacy::TheOnlyCase: TheOnlyCase { a: -1 } }
-
-#![allow(unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
-    Case1 { a: u64, b: u16, c: u16, d: u16, e: u16},
-    Case2 { a: u64, b: u32, c: u32},
-    Case3 { a: u64, b: u64 }
-}
-
-enum Univariant {
-    TheOnlyCase { a: i64 }
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2 = Case2 { a: 0, b: 286331153, c: 286331153 };
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3 = Case3 { a: 0, b: 6438275382588823897 };
-
-    let univariant = TheOnlyCase { a: -1 };
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/tuple-style-enum-legacy.rs b/src/test/debuginfo/tuple-style-enum-legacy.rs
deleted file mode 100644
index ebc8e03..0000000
--- a/src/test/debuginfo/tuple-style-enum-legacy.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:set print union on
-// gdb-command:run
-
-// gdb-command:print case1
-// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, [...]}, {RUST$ENUM$DISR = Case1, [...]}}
-// gdbr-check:$1 = tuple_style_enum_legacy::Regular::Case1(0, 31868, 31868, 31868, 31868)
-
-// gdb-command:print case2
-// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, [...]}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, [...]}}
-// gdbr-check:$2 = tuple_style_enum_legacy::Regular::Case2(0, 286331153, 286331153)
-
-// gdb-command:print case3
-// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, [...]}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}}
-// gdbr-check:$3 = tuple_style_enum_legacy::Regular::Case3(0, 6438275382588823897)
-
-// gdb-command:print univariant
-// gdbg-check:$4 = {{__0 = -1}}
-// gdbr-check:$4 = tuple_style_enum_legacy::Univariant::TheOnlyCase(-1)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print case1
-// lldbg-check:[...]$0 = Case1(0, 31868, 31868, 31868, 31868)
-// lldbr-check:(tuple_style_enum_legacy::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 }
-
-// lldb-command:print case2
-// lldbg-check:[...]$1 = Case2(0, 286331153, 286331153)
-// lldbr-check:(tuple_style_enum_legacy::Regular::Case2) case2 = Case2 { tuple_style_enum_legacy::Regular::Case1: 0, tuple_style_enum_legacy::Regular::Case2: 286331153, tuple_style_enum_legacy::Regular::Case3: 286331153 }
-
-// lldb-command:print case3
-// lldbg-check:[...]$2 = Case3(0, 6438275382588823897)
-// lldbr-check:(tuple_style_enum_legacy::Regular::Case3) case3 = Case3 { tuple_style_enum_legacy::Regular::Case1: 0, tuple_style_enum_legacy::Regular::Case2: 6438275382588823897 }
-
-// lldb-command:print univariant
-// lldbg-check:[...]$3 = TheOnlyCase(-1)
-// lldbr-check:(tuple_style_enum_legacy::Univariant) univariant = { tuple_style_enum_legacy::TheOnlyCase = { = -1 } }
-
-#![allow(unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-use self::Regular::{Case1, Case2, Case3};
-use self::Univariant::TheOnlyCase;
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
-    Case1(u64, u16, u16, u16, u16),
-    Case2(u64, u32, u32),
-    Case3(u64, u64)
-}
-
-enum Univariant {
-    TheOnlyCase(i64)
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let case1 = Case1(0, 31868, 31868, 31868, 31868);
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let case2 = Case2(0, 286331153, 286331153);
-
-    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
-    // 0b01011001010110010101100101011001 = 1499027801
-    // 0b0101100101011001 = 22873
-    // 0b01011001 = 89
-    let case3 = Case3(0, 6438275382588823897);
-
-    let univariant = TheOnlyCase(-1);
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/debuginfo/unique-enum-legacy.rs b/src/test/debuginfo/unique-enum-legacy.rs
deleted file mode 100644
index e7c9357..0000000
--- a/src/test/debuginfo/unique-enum-legacy.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-// ignore-tidy-linelength
-// min-lldb-version: 310
-
-// As long as LLVM 5 and LLVM 6 are supported, we want to test the
-// enum debuginfo fallback mode.  Once those are desupported, this
-// test can be removed, as there is another (non-"legacy") test that
-// tests the new mode.
-// ignore-llvm-version: 7.0 - 9.9.9
-// ignore-gdb-version: 7.11.90 - 7.12.9
-// ignore-gdb-version: 8.2 - 9.9
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:print *the_a
-// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, [...]}}
-// gdbr-check:$1 = unique_enum_legacy::ABC::TheA{x: 0, y: 8970181431921507452}
-
-// gdb-command:print *the_b
-// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, [...]}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}}
-// gdbr-check:$2 = unique_enum_legacy::ABC::TheB(0, 286331153, 286331153)
-
-// gdb-command:print *univariant
-// gdbg-check:$3 = {{__0 = 123234}}
-// gdbr-check:$3 = unique_enum_legacy::Univariant::TheOnlyCase(123234)
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:print *the_a
-// lldbg-check:[...]$0 = TheA { x: 0, y: 8970181431921507452 }
-// lldbr-check:(unique_enum_legacy::ABC::TheA) *the_a = TheA { unique_enum_legacy::ABC::TheA: 0, unique_enum_legacy::ABC::TheB: 8970181431921507452 }
-
-// lldb-command:print *the_b
-// lldbg-check:[...]$1 = TheB(0, 286331153, 286331153)
-// lldbr-check:(unique_enum_legacy::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 }
-
-// lldb-command:print *univariant
-// lldbg-check:[...]$2 = TheOnlyCase(123234)
-// lldbr-check:(unique_enum_legacy::Univariant) *univariant = { unique_enum_legacy::TheOnlyCase = { = 123234 } }
-
-#![allow(unused_variables)]
-#![feature(box_syntax)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
-    TheA { x: i64, y: i64 },
-    TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
-    TheOnlyCase(i64)
-}
-
-fn main() {
-
-    // In order to avoid endianness trouble all of the following test values consist of a single
-    // repeated byte. This way each interpretation of the union should look the same, no matter if
-    // this is a big or little endian machine.
-
-    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
-    // 0b01111100011111000111110001111100 = 2088533116
-    // 0b0111110001111100 = 31868
-    // 0b01111100 = 124
-    let the_a: Box<_> = box ABC::TheA { x: 0, y: 8970181431921507452 };
-
-    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
-    // 0b00010001000100010001000100010001 = 286331153
-    // 0b0001000100010001 = 4369
-    // 0b00010001 = 17
-    let the_b: Box<_> = box ABC::TheB (0, 286331153, 286331153);
-
-    let univariant: Box<_> = box Univariant::TheOnlyCase(123234);
-
-    zzz(); // #break
-}
-
-fn zzz() {()}
diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs
new file mode 100644
index 0000000..f6f7d09
--- /dev/null
+++ b/src/test/mir-opt/const-promotion-extern-static.rs
@@ -0,0 +1,73 @@
+extern "C" {
+    static X: i32;
+}
+
+static Y: i32 = 42;
+
+static mut BAR: *const &'static i32 = [&Y].as_ptr();
+
+static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr();
+
+fn main() {}
+
+// END RUST SOURCE
+// START rustc.FOO.PromoteTemps.before.mir
+// bb0: {
+// ...
+//     _5 = const Scalar(alloc1+0) : &i32;
+//     _4 = &(*_5);
+//     _3 = [move _4];
+//     _2 = &_3;
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     StorageDead(_5);
+//     StorageDead(_3);
+//     return;
+// }
+// END rustc.FOO.PromoteTemps.before.mir
+// START rustc.BAR.PromoteTemps.before.mir
+// bb0: {
+// ...
+//     _5 = const Scalar(alloc0+0) : &i32;
+//     _4 = &(*_5);
+//     _3 = [move _4];
+//     _2 = &_3;
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     StorageDead(_5);
+//     StorageDead(_3);
+//     return;
+// }
+// END rustc.BAR.PromoteTemps.before.mir
+// START rustc.BAR.PromoteTemps.after.mir
+// bb0: {
+// ...
+//     _6 = const BAR::promoted[0];
+//     _2 = &(*_6);
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     return;
+// }
+// END rustc.BAR.PromoteTemps.after.mir
+// START rustc.FOO.PromoteTemps.after.mir
+// bb0: {
+// ...
+//     _6 = const FOO::promoted[0];
+//     _2 = &(*_6);
+//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+// }
+// ...
+// bb2: {
+//     return;
+// }
+// END rustc.FOO.PromoteTemps.after.mir
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs
index d9e0eb6..693ef78 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.rs
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -10,10 +10,10 @@
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(AllocId(0).0x0) : &u8;
+//      _3 = const Scalar(alloc0+0) : &u8;
 //      _2 = (*_3);
 //      ...
-//      _5 = const Scalar(AllocId(0).0x0) : &u8;
+//      _5 = const Scalar(alloc0+0) : &u8;
 //      _4 = (*_5);
 //      _1 = Add(move _2, move _4);
 //      ...
diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs
index d45ffdc..8b48296 100644
--- a/src/test/mir-opt/const_prop/ref_deref.rs
+++ b/src/test/mir-opt/const_prop/ref_deref.rs
@@ -3,10 +3,29 @@
 }
 
 // END RUST SOURCE
+// START rustc.main.PromoteTemps.before.mir
+// bb0: {
+//     ...
+//     _3 = const 4i32;
+//     _2 = &_3;
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.before.mir
+// START rustc.main.PromoteTemps.after.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &(*_4);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.after.mir
 // START rustc.main.ConstProp.before.mir
 // bb0: {
 //     ...
-//     _2 = &(promoted[0]: i32);
+//     _4 = const main::promoted[0];
+//     _2 = _4;
 //     _1 = (*_2);
 //     ...
 //}
@@ -14,7 +33,8 @@
 // START rustc.main.ConstProp.after.mir
 // bb0: {
 //     ...
-//     _2 = &(promoted[0]: i32);
+//     _4 = const main::promoted[0];
+//     _2 = _4;
 //     _1 = const 4i32;
 //     ...
 // }
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs
new file mode 100644
index 0000000..ca539fb
--- /dev/null
+++ b/src/test/mir-opt/const_prop/ref_deref_project.rs
@@ -0,0 +1,41 @@
+fn main() {
+    *(&(4, 5).1); // This does not currently propagate (#67862)
+}
+
+// END RUST SOURCE
+// START rustc.main.PromoteTemps.before.mir
+// bb0: {
+//     ...
+//     _3 = (const 4i32, const 5i32);
+//     _2 = &(_3.1: i32);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.before.mir
+// START rustc.main.PromoteTemps.after.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &((*_4).1: i32);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.PromoteTemps.after.mir
+// START rustc.main.ConstProp.before.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &((*_4).1: i32);
+//     _1 = (*_2);
+//     ...
+//}
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+// bb0: {
+//     ...
+//     _4 = const main::promoted[0];
+//     _2 = &((*_4).1: i32);
+//     _1 = (*_2);
+//     ...
+// }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index d6ff76b..43813e4 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -6,7 +6,8 @@
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _4 = &(promoted[0]: [u32; 3]);
+//      _9 = const main::promoted[0];
+//      _4 = _9;
 //      _3 = _4;
 //      _2 = move _3 as &[u32] (Pointer(Unsize));
 //      ...
@@ -24,7 +25,8 @@
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _4 = &(promoted[0]: [u32; 3]);
+//      _9 = const main::promoted[0];
+//      _4 = _9;
 //      _3 = _4;
 //      _2 = move _3 as &[u32] (Pointer(Unsize));
 //      ...
diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs
index 0bb9dfa..f368bde 100644
--- a/src/test/mir-opt/inline/inline-into-box-place.rs
+++ b/src/test/mir-opt/inline/inline-into-box-place.rs
@@ -1,5 +1,6 @@
 // ignore-tidy-linelength
 // ignore-wasm32-bare compiled with panic=abort by default
+// compile-flags: -Z mir-opt-level=3
 #![feature(box_syntax)]
 
 fn main() {
diff --git a/src/test/mir-opt/inline/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs
index 6cdbcfd..7b78fc3 100644
--- a/src/test/mir-opt/inline/inline-retag.rs
+++ b/src/test/mir-opt/inline/inline-retag.rs
@@ -25,11 +25,11 @@
 //         ...
 //         Retag(_3);
 //         Retag(_6);
-//         StorageLive(_9);
-//         _9 = (*_3);
-//         StorageLive(_10);
-//         _10 = (*_6);
-//         _0 = Eq(move _9, move _10);
+//         StorageLive(_11);
+//         _11 = (*_3);
+//         StorageLive(_12);
+//         _12 = (*_6);
+//         _0 = Eq(move _11, move _12);
 //         ...
 //         return;
 //     }
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index 648856b..2c20c35 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -65,7 +65,8 @@
 //  }
 //  bb6: { // binding1 and guard
 //      StorageLive(_6);
-//      _6 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
+//      _11 = const full_tested_match::promoted[0];
+//      _6 = &(((*_11) as Some).0: i32);
 //      _4 = &shallow _2;
 //      StorageLive(_7);
 //      _7 = const guard() -> [return: bb7, unwind: bb1];
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index ccecaea..1c88a9e 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -113,8 +113,8 @@
 //     }
 // }
 // END rustc.main-{{closure}}.EraseRegions.after.mir
-// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
-// fn  std::ptr::real_drop_in_place(_1: &mut Test) -> () {
+// START rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+// fn  std::intrinsics::drop_in_place(_1: *mut Test) -> () {
 //     ...
 //     bb0: {
 //         Retag([raw] _1);
@@ -126,4 +126,4 @@
 //         return;
 //     }
 // }
-// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+// END rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index 656b405..d85eff4 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -47,25 +47,22 @@
 //     }
 //     bb0: {
 //         _5 = discriminant(_1);
-//         switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
+//         switchInt(move _5) -> [0isize: bb3, otherwise: bb1];
 //     }
 //     bb1: {
-//         unreachable;
-//     }
-//     bb2: {
 //         _6 = ((_1 as Err).0: i32);
 //         ((_0 as Err).0: i32) = move _6;
 //         discriminant(_0) = 1;
-//         goto -> bb3;
+//         goto -> bb2;
 //     }
-//     bb3: {
+//     bb2: {
 //         return;
 //     }
-//     bb4: {
+//     bb3: {
 //         _10 = ((_1 as Ok).0: u32);
 //         ((_0 as Ok).0: u32) = move _10;
 //         discriminant(_0) = 0;
-//         goto -> bb3;
+//         goto -> bb2;
 //     }
 // }
 // END rustc.try_identity.SimplifyArmIdentity.before.mir
@@ -109,25 +106,22 @@
 //     }
 //     bb0: {
 //         _5 = discriminant(_1);
-//         switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
+//         switchInt(move _5) -> [0isize: bb3, otherwise: bb1];
 //     }
 //     bb1: {
-//         unreachable;
+//         _0 = move _1;
+//         nop;
+//         nop;
+//         goto -> bb2;
 //     }
 //     bb2: {
-//         _0 = move _1;
-//         nop;
-//         nop;
-//         goto -> bb3;
-//     }
-//     bb3: {
 //         return;
 //     }
-//     bb4: {
+//     bb3: {
 //         _0 = move _1;
 //         nop;
 //         nop;
-//         goto -> bb3;
+//         goto -> bb2;
 //     }
 // }
 // END rustc.try_identity.SimplifyArmIdentity.after.mir
diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs
index 5a37b67..a253755 100644
--- a/src/test/mir-opt/slice-drop-shim.rs
+++ b/src/test/mir-opt/slice-drop-shim.rs
@@ -6,7 +6,7 @@
 
 // END RUST SOURCE
 
-// START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+// START rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
 // let mut _2: usize;
 // let mut _3: usize;
 // let mut _4: usize;
@@ -87,4 +87,4 @@
 //     _3 = Len((*_1));
 //     switchInt(move _2) -> [0usize: bb8, otherwise: bb14];
 // }
-// END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+// END rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs
index f2e1864..d587d23 100644
--- a/src/test/mir-opt/uniform_array_move_out.rs
+++ b/src/test/mir-opt/uniform_array_move_out.rs
@@ -1,5 +1,4 @@
 #![feature(box_syntax)]
-#![feature(slice_patterns)]
 
 fn move_out_from_end() {
     let a = [box 1, box 2];
diff --git a/src/test/mir-opt/uninhabited_enum_branching.rs b/src/test/mir-opt/uninhabited_enum_branching.rs
index aa56918..dda5fd4 100644
--- a/src/test/mir-opt/uninhabited_enum_branching.rs
+++ b/src/test/mir-opt/uninhabited_enum_branching.rs
@@ -45,53 +45,47 @@
 //   StorageLive(_2);
 //   _2 = Test1::C;
 //   _3 = discriminant(_2);
-//   switchInt(move _3) -> [0isize: bb3, 1isize: bb4, 2isize: bb1, otherwise: bb2];
+//   switchInt(move _3) -> [0isize: bb2, 1isize: bb3, otherwise: bb1];
 // }
 // bb1: {
 //   StorageLive(_5);
 //   _5 = const "C";
 //   _1 = &(*_5);
 //   StorageDead(_5);
-//   goto -> bb5;
+//   goto -> bb4;
 // }
 // bb2: {
-//   unreachable;
+//   _1 = const "A(Empty)";
+//   goto -> bb4;
 // }
 // bb3: {
-//   _1 = const "A(Empty)";
-//   goto -> bb5;
-// }
-// bb4: {
 //   StorageLive(_4);
 //   _4 = const "B(Empty)";
 //   _1 = &(*_4);
 //   StorageDead(_4);
-//   goto -> bb5;
+//   goto -> bb4;
 // }
-// bb5: {
+// bb4: {
 //   StorageDead(_2);
 //   StorageDead(_1);
 //   StorageLive(_6);
 //   StorageLive(_7);
 //   _7 = Test2::D;
 //   _8 = discriminant(_7);
-//   switchInt(move _8) -> [4isize: bb8, 5isize: bb6, otherwise: bb7];
+//   switchInt(move _8) -> [4isize: bb6, otherwise: bb5];
 // }
-// bb6: {
+// bb5: {
 //   StorageLive(_9);
 //   _9 = const "E";
 //   _6 = &(*_9);
 //   StorageDead(_9);
-//   goto -> bb9;
+//   goto -> bb7;
+// }
+// bb6: {
+//   _6 = const "D";
+//   goto -> bb7;
 // }
 // bb7: {
-//   unreachable;
-// }
-// bb8: {
-//   _6 = const "D";
-//   goto -> bb9;
-// }
-// bb9: {
 //   StorageDead(_7);
 //   StorageDead(_6);
 //   _0 = ();
@@ -114,53 +108,47 @@
 //   StorageLive(_2);
 //   _2 = Test1::C;
 //   _3 = discriminant(_2);
-//   switchInt(move _3) -> [2isize: bb1, otherwise: bb2];
+//   switchInt(move _3) -> bb1;
 // }
 // bb1: {
 //   StorageLive(_5);
 //   _5 = const "C";
 //   _1 = &(*_5);
 //   StorageDead(_5);
-//   goto -> bb5;
+//   goto -> bb4;
 // }
 // bb2: {
-//   unreachable;
+//   _1 = const "A(Empty)";
+//   goto -> bb4;
 // }
 // bb3: {
-//   _1 = const "A(Empty)";
-//   goto -> bb5;
-// }
-// bb4: {
 //   StorageLive(_4);
 //   _4 = const "B(Empty)";
 //   _1 = &(*_4);
 //   StorageDead(_4);
-//   goto -> bb5;
+//   goto -> bb4;
 // }
-// bb5: {
+// bb4: {
 //   StorageDead(_2);
 //   StorageDead(_1);
 //   StorageLive(_6);
 //   StorageLive(_7);
 //   _7 = Test2::D;
 //   _8 = discriminant(_7);
-//   switchInt(move _8) -> [4isize: bb8, 5isize: bb6, otherwise: bb7];
+//   switchInt(move _8) -> [4isize: bb6, otherwise: bb5];
 // }
-// bb6: {
+// bb5: {
 //   StorageLive(_9);
 //   _9 = const "E";
 //   _6 = &(*_9);
 //   StorageDead(_9);
-//   goto -> bb9;
+//   goto -> bb7;
+// }
+// bb6: {
+//   _6 = const "D";
+//   goto -> bb7;
 // }
 // bb7: {
-//   unreachable;
-// }
-// bb8: {
-//   _6 = const "D";
-//   goto -> bb9;
-// }
-// bb9: {
 //   StorageDead(_7);
 //   StorageDead(_6);
 //   _0 = ();
@@ -183,9 +171,6 @@
 //   StorageLive(_2);
 //   _2 = Test1::C;
 //   _3 = discriminant(_2);
-//   switchInt(move _3) -> [2isize: bb1, otherwise: bb2];
-// }
-// bb1: {
 //   StorageLive(_5);
 //   _5 = const "C";
 //   _1 = &(*_5);
@@ -196,26 +181,20 @@
 //   StorageLive(_7);
 //   _7 = Test2::D;
 //   _8 = discriminant(_7);
-//   switchInt(move _8) -> [4isize: bb5, 5isize: bb3, otherwise: bb4];
+//   switchInt(move _8) -> [4isize: bb2, otherwise: bb1];
 // }
-// bb2: {
-//   unreachable;
-// }
-// bb3: {
+// bb1: {
 //   StorageLive(_9);
 //   _9 = const "E";
 //   _6 = &(*_9);
 //   StorageDead(_9);
-//   goto -> bb6;
+//   goto -> bb3;
 // }
-// bb4: {
-//   unreachable;
-// }
-// bb5: {
+// bb2: {
 //   _6 = const "D";
-//   goto -> bb6;
+//   goto -> bb3;
 // }
-// bb6: {
+// bb3: {
 //   StorageDead(_7);
 //   StorageDead(_6);
 //   _0 = ();
diff --git a/src/test/mir-opt/unreachable.rs b/src/test/mir-opt/unreachable.rs
new file mode 100644
index 0000000..fa5c1a0
--- /dev/null
+++ b/src/test/mir-opt/unreachable.rs
@@ -0,0 +1,78 @@
+enum Empty {}
+
+fn empty() -> Option<Empty> {
+    None
+}
+
+fn main() {
+    if let Some(_x) = empty() {
+        let mut _y;
+
+        if true {
+            _y = 21;
+        } else {
+            _y = 42;
+        }
+
+        match _x { }
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.UnreachablePropagation.before.mir
+//      bb0: {
+//          StorageLive(_1);
+//          _1 = const empty() -> bb1;
+//      }
+//      bb1: {
+//          _2 = discriminant(_1);
+//          switchInt(move _2) -> [1isize: bb3, otherwise: bb2];
+//      }
+//      bb2: {
+//          _0 = ();
+//          StorageDead(_1);
+//          return;
+//      }
+//      bb3: {
+//          StorageLive(_3);
+//          _3 = move ((_1 as Some).0: Empty);
+//          StorageLive(_4);
+//          StorageLive(_5);
+//          StorageLive(_6);
+//          _6 = const true;
+//          switchInt(_6) -> [false: bb4, otherwise: bb5];
+//      }
+//      bb4: {
+//          _4 = const 42i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb5: {
+//          _4 = const 21i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb6: {
+//          StorageDead(_6);
+//          StorageDead(_5);
+//          StorageLive(_7);
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.before.mir
+// START rustc.main.UnreachablePropagation.after.mir
+//      bb0: {
+//          StorageLive(_1);
+//          _1 = const empty() -> bb1;
+//      }
+//      bb1: {
+//          _2 = discriminant(_1);
+//          goto -> bb2;
+//      }
+//      bb2: {
+//          _0 = ();
+//          StorageDead(_1);
+//          return;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.after.mir
diff --git a/src/test/mir-opt/unreachable_asm.rs b/src/test/mir-opt/unreachable_asm.rs
new file mode 100644
index 0000000..ca614ac
--- /dev/null
+++ b/src/test/mir-opt/unreachable_asm.rs
@@ -0,0 +1,72 @@
+// ignore-tidy-linelength
+#![feature(asm)]
+
+enum Empty {}
+
+fn empty() -> Option<Empty> {
+    None
+}
+
+fn main() {
+    if let Some(_x) = empty() {
+        let mut _y;
+
+        if true {
+            _y = 21;
+        } else {
+            _y = 42;
+        }
+
+        // asm instruction stops unreachable propagation to if else blocks bb4 and bb5.
+        unsafe { asm!("NOP"); }
+        match _x { }
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.UnreachablePropagation.before.mir
+//      bb4: {
+//          _4 = const 42i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb5: {
+//          _4 = const 21i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb6: {
+//          StorageDead(_6);
+//          StorageDead(_5);
+//          StorageLive(_7);
+//          asm!(InlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []);
+//          _7 = ();
+//          StorageDead(_7);
+//          StorageLive(_8);
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.before.mir
+// START rustc.main.UnreachablePropagation.after.mir
+//      bb4: {
+//          _4 = const 42i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb5: {
+//          _4 = const 21i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb6: {
+//          StorageDead(_6);
+//          StorageDead(_5);
+//          StorageLive(_7);
+//          asm!(InlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []);
+//          _7 = ();
+//          StorageDead(_7);
+//          StorageLive(_8);
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.after.mir
diff --git a/src/test/mir-opt/unreachable_asm_2.rs b/src/test/mir-opt/unreachable_asm_2.rs
new file mode 100644
index 0000000..8fdbcfb
--- /dev/null
+++ b/src/test/mir-opt/unreachable_asm_2.rs
@@ -0,0 +1,84 @@
+// ignore-tidy-linelength
+#![feature(asm)]
+
+enum Empty {}
+
+fn empty() -> Option<Empty> {
+    None
+}
+
+fn main() {
+    if let Some(_x) = empty() {
+        let mut _y;
+
+        if true {
+            // asm instruction stops unreachable propagation to block bb3.
+            unsafe { asm!("NOP"); }
+            _y = 21;
+        } else {
+            // asm instruction stops unreachable propagation to block bb3.
+            unsafe { asm!("NOP"); }
+            _y = 42;
+        }
+
+        match _x { }
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.UnreachablePropagation.before.mir
+//      bb3: {
+//          ...
+//          switchInt(_6) -> [false: bb4, otherwise: bb5];
+//      }
+//      bb4: {
+//          StorageLive(_8);
+//          asm!(InlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []);
+//          _8 = ();
+//          StorageDead(_8);
+//          _4 = const 42i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//          bb5: {
+//          StorageLive(_7);
+//          asm!(InlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []);
+//          _7 = ();
+//          StorageDead(_7);
+//          _4 = const 21i32;
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb6: {
+//          StorageDead(_6);
+//          StorageDead(_5);
+//          StorageLive(_9);
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.before.mir
+// START rustc.main.UnreachablePropagation.after.mir
+//      bb3: {
+//          ...
+//          switchInt(_6) -> [false: bb4, otherwise: bb5];
+//      }
+//      bb4: {
+//          StorageLive(_8);
+//          asm!(InlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []);
+//          _8 = ();
+//          StorageDead(_8);
+//          _4 = const 42i32;
+//          _5 = ();
+//          unreachable;
+//      }
+//          bb5: {
+//          StorageLive(_7);
+//          asm!(InlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []);
+//          _7 = ();
+//          StorageDead(_7);
+//          _4 = const 21i32;
+//          _5 = ();
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.after.mir
diff --git a/src/test/mir-opt/unreachable_diverging.rs b/src/test/mir-opt/unreachable_diverging.rs
new file mode 100644
index 0000000..bf05019
--- /dev/null
+++ b/src/test/mir-opt/unreachable_diverging.rs
@@ -0,0 +1,65 @@
+pub enum Empty {}
+
+fn empty() -> Option<Empty> {
+    None
+}
+
+fn loop_forever() {
+    loop {}
+}
+
+fn main() {
+    let x = true;
+    if let Some(bomb) = empty() {
+        if x {
+            loop_forever()
+        }
+        match bomb {}
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.UnreachablePropagation.before.mir
+//      bb3: {
+//          StorageLive(_4);
+//          _4 = move ((_2 as Some).0: Empty);
+//          StorageLive(_5);
+//          StorageLive(_6);
+//          _6 = _1;
+//          switchInt(_6) -> [false: bb4, otherwise: bb5];
+//      }
+//      bb4: {
+//          _5 = ();
+//          goto -> bb6;
+//      }
+//      bb5: {
+//          _5 = const loop_forever() -> bb6;
+//      }
+//      bb6: {
+//          StorageDead(_6);
+//          StorageDead(_5);
+//          StorageLive(_7);
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.before.mir
+// START rustc.main.UnreachablePropagation.after.mir
+//      bb3: {
+//          StorageLive(_4);
+//          _4 = move ((_2 as Some).0: Empty);
+//          StorageLive(_5);
+//          StorageLive(_6);
+//          _6 = _1;
+//          goto -> bb4;
+//      }
+//      bb4: {
+//          _5 = const loop_forever() -> bb5;
+//      }
+//      bb5: {
+//          StorageDead(_6);
+//          StorageDead(_5);
+//          StorageLive(_7);
+//          unreachable;
+//      }
+//  }
+// END rustc.main.UnreachablePropagation.after.mir
diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs
index f4d848d..88cfb62 100644
--- a/src/test/mir-opt/unusual-item-types.rs
+++ b/src/test/mir-opt/unusual-item-types.rs
@@ -45,7 +45,7 @@
 // }
 // END rustc.E-V-{{constant}}.mir_map.0.mir
 
-// START rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+// START rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
 //     bb0: {
 //     goto -> bb7;
 // }
@@ -71,7 +71,7 @@
 //     _2 = &mut (*_1);
 //     _3 = const <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5];
 // }
-// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+// END rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
 
 // START rustc.Test-X-{{constructor}}.mir_map.0.mir
 // fn Test::X(_1: usize) -> Test {
diff --git a/src/test/pretty/top-level-doc-comments.rs b/src/test/pretty/top-level-doc-comments.rs
index 16f95d3..b979271 100644
--- a/src/test/pretty/top-level-doc-comments.rs
+++ b/src/test/pretty/top-level-doc-comments.rs
@@ -1,11 +1,6 @@
 /// Some doc comment.
 struct X;
 
-// ignore-license
-
-// http://rust-lang.org/COPYRIGHT.
-//
-
 // pp-exact
 
 // Test that rust can properly pretty print a doc comment if it's the first line in a file.  some
diff --git a/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c b/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c
index a975549..fea490c 100644
--- a/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c
+++ b/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c
@@ -1,4 +1,3 @@
-// ignore-license
 #ifdef _WIN32
 __declspec(dllexport)
 #endif
diff --git a/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c b/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c
index b284932..fea490c 100644
--- a/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c
+++ b/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c
@@ -1,5 +1,3 @@
-// ignore-license
-
 #ifdef _WIN32
 __declspec(dllexport)
 #endif
diff --git a/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c b/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c
index 5729d41..bb4036b 100644
--- a/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c
+++ b/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c
@@ -1,4 +1,3 @@
-// ignore-license
 void foo();
 
 int main() {
diff --git a/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c
index 5729d41..bb4036b 100644
--- a/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c
+++ b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c
@@ -1,4 +1,3 @@
-// ignore-license
 void foo();
 
 int main() {
diff --git a/src/test/run-make-fulldeps/c-static-dylib/cfoo.c b/src/test/run-make-fulldeps/c-static-dylib/cfoo.c
index 113717a..9fe07f8 100644
--- a/src/test/run-make-fulldeps/c-static-dylib/cfoo.c
+++ b/src/test/run-make-fulldeps/c-static-dylib/cfoo.c
@@ -1,2 +1 @@
-// ignore-license
 int foo() { return 0; }
diff --git a/src/test/run-make-fulldeps/c-static-rlib/cfoo.c b/src/test/run-make-fulldeps/c-static-rlib/cfoo.c
index 113717a..9fe07f8 100644
--- a/src/test/run-make-fulldeps/c-static-rlib/cfoo.c
+++ b/src/test/run-make-fulldeps/c-static-rlib/cfoo.c
@@ -1,2 +1 @@
-// ignore-license
 int foo() { return 0; }
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile b/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile
new file mode 100644
index 0000000..5c9b2d1
--- /dev/null
+++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile
@@ -0,0 +1,27 @@
+include ../tools.mk
+
+TARGET_SYSROOT := $(shell $(RUSTC) --print sysroot)/lib/rustlib/$(TARGET)/lib
+
+ifdef IS_MSVC
+LIBSTD := $(wildcard $(TARGET_SYSROOT)/libstd-*.dll.lib)
+else
+LIBSTD := $(wildcard $(TARGET_SYSROOT)/$(call DYLIB_GLOB,std))
+STD := $(basename $(patsubst lib%,%, $(notdir $(LIBSTD))))
+endif
+
+all: $(call RUN_BINFILE,foo)
+	$(call RUN,foo)
+
+ifdef IS_MSVC
+CLIBS := $(TMPDIR)/foo.dll.lib $(TMPDIR)/bar.dll.lib $(LIBSTD)
+$(call RUN_BINFILE,foo): $(call DYLIB,foo)
+	$(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo)
+else
+CLIBS := -lfoo -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT)
+$(call RUN_BINFILE,foo): $(call DYLIB,foo)
+	$(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo)
+endif
+
+$(call DYLIB,foo):
+	$(RUSTC) -C prefer-dynamic bar.rs
+	$(RUSTC) foo.rs
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs
new file mode 100644
index 0000000..b3a7539
--- /dev/null
+++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs
@@ -0,0 +1,5 @@
+#![crate_type = "dylib"]
+
+pub fn bar() {
+    println!("hello!");
+}
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c
new file mode 100644
index 0000000..154f968
--- /dev/null
+++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c
@@ -0,0 +1,10 @@
+#include <assert.h>
+
+extern void foo();
+extern unsigned bar(unsigned a, unsigned b);
+
+int main() {
+  foo();
+  assert(bar(1, 2) == 3);
+  return 0;
+}
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
new file mode 100644
index 0000000..c2cc3af
--- /dev/null
+++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
@@ -0,0 +1,13 @@
+#![crate_type = "cdylib"]
+
+extern crate bar;
+
+#[no_mangle]
+pub extern fn foo() {
+    bar::bar();
+}
+
+#[no_mangle]
+pub extern fn bar(a: u32, b: u32) -> u32 {
+    a + b
+}
diff --git a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp
index aac3ba4..4c2fb9c 100644
--- a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp
+++ b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp
@@ -1,4 +1,3 @@
-// ignore-license
 extern "C" void foo() {
     int *a = new int(3);
     delete a;
diff --git a/src/test/run-make-fulldeps/extern-fn-generic/test.c b/src/test/run-make-fulldeps/extern-fn-generic/test.c
index f9faef6..a8504ff 100644
--- a/src/test/run-make-fulldeps/extern-fn-generic/test.c
+++ b/src/test/run-make-fulldeps/extern-fn-generic/test.c
@@ -1,4 +1,3 @@
-// ignore-license
 #include <stdint.h>
 
 typedef struct TestStruct {
diff --git a/src/test/run-make-fulldeps/extern-fn-mangle/test.c b/src/test/run-make-fulldeps/extern-fn-mangle/test.c
index 1a9855d..e94d750 100644
--- a/src/test/run-make-fulldeps/extern-fn-mangle/test.c
+++ b/src/test/run-make-fulldeps/extern-fn-mangle/test.c
@@ -1,4 +1,3 @@
-// ignore-license
 #include <stdint.h>
 
 uint32_t foo();
diff --git a/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c b/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c
index c3d6166..3b6fb4c 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c
+++ b/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c
@@ -1,4 +1,3 @@
-// ignore-license
 #include <stdio.h>
 #include <stdint.h>
 
diff --git a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c
index 4124e20..52af3dc 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c
+++ b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c
@@ -1,4 +1,3 @@
-// ignore-license
 // Pragma needed cause of gcc bug on windows: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
 
 #include <assert.h>
diff --git a/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c b/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c
index 8c87c23..86cb645 100644
--- a/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c
+++ b/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c
@@ -1,4 +1,3 @@
-// ignore-license
 #include <stdio.h>
 #include <stdint.h>
 
diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
index 399c78f..9c2045c 100644
--- a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
+++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs
@@ -4,7 +4,6 @@
 
 // For linking libstdc++ on MinGW
 #![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))]
-
 #![feature(unwind_attributes)]
 
 use std::panic::{catch_unwind, AssertUnwindSafe};
diff --git a/src/test/run-make-fulldeps/glibc-staticlib-args/program.c b/src/test/run-make-fulldeps/glibc-staticlib-args/program.c
index d704c39..30f6974 100644
--- a/src/test/run-make-fulldeps/glibc-staticlib-args/program.c
+++ b/src/test/run-make-fulldeps/glibc-staticlib-args/program.c
@@ -1,4 +1,3 @@
-// ignore-license
 void args_check();
 
 int main() {
diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c
index c761f02..812c975 100644
--- a/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c
+++ b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c
@@ -1,4 +1,3 @@
-// ignore-license
 void foo();
 
 void bar() { foo(); }
diff --git a/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c
index 2895ad4..85e6cd8 100644
--- a/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c
+++ b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c
@@ -1,2 +1 @@
-// ignore-license
 void foo() {}
diff --git a/src/test/run-make-fulldeps/issue-25581/test.c b/src/test/run-make-fulldeps/issue-25581/test.c
index 5736b17..52fbf78 100644
--- a/src/test/run-make-fulldeps/issue-25581/test.c
+++ b/src/test/run-make-fulldeps/issue-25581/test.c
@@ -1,4 +1,3 @@
-// ignore-license
 #include <stddef.h>
 #include <stdint.h>
 
diff --git a/src/test/run-make-fulldeps/issue64319/Makefile b/src/test/run-make-fulldeps/issue64319/Makefile
new file mode 100644
index 0000000..5592f5a
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue64319/Makefile
@@ -0,0 +1,39 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# Different optimization levels imply different values for `-Zshare-generics`,
+# so try out a whole bunch of combinations to make sure everything is compatible
+all:
+	# First up, try some defaults
+	$(RUSTC) --crate-type rlib foo.rs
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=3
+
+	# Next try mixing up some things explicitly
+	$(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
+	$(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
+	$(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
+	$(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
+
+	# Now combine a whole bunch of options together
+	$(RUSTC) --crate-type rlib foo.rs
+	$(RUSTC) --crate-type dylib bar.rs
+	$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=1
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=2
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=3
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=s
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=z
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no
+	$(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes
diff --git a/src/test/run-make-fulldeps/issue64319/bar.rs b/src/test/run-make-fulldeps/issue64319/bar.rs
new file mode 100644
index 0000000..3895c0b
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue64319/bar.rs
@@ -0,0 +1,5 @@
+extern crate foo;
+
+pub fn bar() {
+    foo::foo();
+}
diff --git a/src/test/run-make-fulldeps/issue64319/foo.rs b/src/test/run-make-fulldeps/issue64319/foo.rs
new file mode 100644
index 0000000..c54a238
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue64319/foo.rs
@@ -0,0 +1,9 @@
+pub fn foo() {
+    bar::<usize>();
+}
+
+pub fn bar<T>() {
+    baz();
+}
+
+fn baz() {}
diff --git a/src/test/run-make-fulldeps/libtest-json/output-default.json b/src/test/run-make-fulldeps/libtest-json/output-default.json
index 8046d72..0cd9ab7 100644
--- a/src/test/run-make-fulldeps/libtest-json/output-default.json
+++ b/src/test/run-make-fulldeps/libtest-json/output-default.json
@@ -2,7 +2,7 @@
 { "type": "test", "event": "started", "name": "a" }
 { "type": "test", "name": "a", "event": "ok" }
 { "type": "test", "event": "started", "name": "b" }
-{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" }
+{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" }
 { "type": "test", "event": "started", "name": "c" }
 { "type": "test", "name": "c", "event": "ok" }
 { "type": "test", "event": "started", "name": "d" }
diff --git a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
index 3033162..dfaf005 100644
--- a/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
+++ b/src/test/run-make-fulldeps/libtest-json/output-stdout-success.json
@@ -2,7 +2,7 @@
 { "type": "test", "event": "started", "name": "a" }
 { "type": "test", "name": "a", "event": "ok", "stdout": "print from successful test\n" }
 { "type": "test", "event": "started", "name": "b" }
-{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.\n" }
+{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:9:5\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n" }
 { "type": "test", "event": "started", "name": "c" }
 { "type": "test", "name": "c", "event": "ok", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:15:5\n" }
 { "type": "test", "event": "started", "name": "d" }
diff --git a/src/test/run-make-fulldeps/link-path-order/correct.c b/src/test/run-make-fulldeps/link-path-order/correct.c
index a595939..3064af9 100644
--- a/src/test/run-make-fulldeps/link-path-order/correct.c
+++ b/src/test/run-make-fulldeps/link-path-order/correct.c
@@ -1,2 +1 @@
-// ignore-license
 int should_return_one() { return 1; }
diff --git a/src/test/run-make-fulldeps/link-path-order/wrong.c b/src/test/run-make-fulldeps/link-path-order/wrong.c
index c53e7e3..64275b3 100644
--- a/src/test/run-make-fulldeps/link-path-order/wrong.c
+++ b/src/test/run-make-fulldeps/link-path-order/wrong.c
@@ -1,2 +1 @@
-// ignore-license
 int should_return_one() { return 0; }
diff --git a/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c b/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c
index d7d33ea..78a6934 100644
--- a/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c
+++ b/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c
@@ -1,4 +1,3 @@
-// ignore-license
 #include <stdint.h>
 
 extern int32_t BAZ;
diff --git a/src/test/run-make-fulldeps/lto-smoke-c/bar.c b/src/test/run-make-fulldeps/lto-smoke-c/bar.c
index 5729d41..bb4036b 100644
--- a/src/test/run-make-fulldeps/lto-smoke-c/bar.c
+++ b/src/test/run-make-fulldeps/lto-smoke-c/bar.c
@@ -1,4 +1,3 @@
-// ignore-license
 void foo();
 
 int main() {
diff --git a/src/test/run-make-fulldeps/manual-link/bar.c b/src/test/run-make-fulldeps/manual-link/bar.c
index 3c167b4..e425999 100644
--- a/src/test/run-make-fulldeps/manual-link/bar.c
+++ b/src/test/run-make-fulldeps/manual-link/bar.c
@@ -1,2 +1 @@
-// ignore-license
 void bar() {}
diff --git a/src/test/run-make-fulldeps/manual-link/foo.c b/src/test/run-make-fulldeps/manual-link/foo.c
index 3c167b4..e425999 100644
--- a/src/test/run-make-fulldeps/manual-link/foo.c
+++ b/src/test/run-make-fulldeps/manual-link/foo.c
@@ -1,2 +1 @@
-// ignore-license
 void bar() {}
diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile
deleted file mode 100644
index 3a377c3..0000000
--- a/src/test/run-make-fulldeps/sanitizer-address/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-# needs-sanitizer-support
-
--include ../tools.mk
-
-LOG := $(TMPDIR)/log.txt
-
-# NOTE the address sanitizer only supports x86_64 linux and macOS
-
-ifeq ($(TARGET),x86_64-apple-darwin)
-EXTRA_RUSTFLAG=-C rpath
-else
-ifeq ($(TARGET),x86_64-unknown-linux-gnu)
-
-# Apparently there are very specific Linux kernels, notably the one that's
-# currently on Travis CI, which contain a buggy commit that triggers failures in
-# the ASan implementation, detailed at google/sanitizers#837. As noted in
-# google/sanitizers#856 the "fix" is to avoid using PIE binaries, so we pass a
-# different relocation model to avoid generating a PIE binary. Once Travis is no
-# longer running kernel 4.4.0-93 we can remove this and pass an empty set of
-# flags again.
-EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic
-endif
-endif
-
-all:
-	$(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan
-	# Verify that stack buffer overflow is detected:
-	$(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow
-	# Verify that variable name is included in address sanitizer report:
-	$(TMPDIR)/overflow 2>&1 | $(CGREP) "'xs'"
diff --git a/src/test/run-make-fulldeps/sanitizer-address/overflow.rs b/src/test/run-make-fulldeps/sanitizer-address/overflow.rs
deleted file mode 100644
index b997a74..0000000
--- a/src/test/run-make-fulldeps/sanitizer-address/overflow.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let xs = [0, 1, 2, 3];
-    let _y = unsafe { *xs.as_ptr().offset(4) };
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile
deleted file mode 100644
index 9581ac5..0000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# needs-sanitizer-support
-
--include ../tools.mk
-
-# NOTE the address sanitizer only supports x86_64 linux and macOS
-
-ifeq ($(TARGET),x86_64-apple-darwin)
-EXTRA_RUSTFLAG=-C rpath
-else
-ifeq ($(TARGET),x86_64-unknown-linux-gnu)
-EXTRA_RUSTFLAG=
-endif
-endif
-
-all:
-	$(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | $(CGREP) '-Z sanitizer'
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs
deleted file mode 100644
index e7a11a9..0000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    println!("Hello, world!");
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
deleted file mode 100644
index df8afee..0000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
--include ../tools.mk
-
-all:
-	$(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \
-		$(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` target'
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs
deleted file mode 100644
index d3dd5ed..0000000
--- a/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![feature(no_core)]
-#![no_core]
-#![no_main]
diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile
deleted file mode 100644
index 101e827..0000000
--- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
--include ../tools.mk
-
-# needs-sanitizer-support
-# only-linux
-# only-x86_64
-# ignore-test
-# FIXME(#46126) ThinLTO for libstd broke this test
-
-all:
-	$(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_lsan
-	$(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks'
diff --git a/src/test/run-make-fulldeps/sanitizer-leak/leak.rs b/src/test/run-make-fulldeps/sanitizer-leak/leak.rs
deleted file mode 100644
index ab8df5c..0000000
--- a/src/test/run-make-fulldeps/sanitizer-leak/leak.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use std::mem;
-
-fn main() {
-    let xs = vec![1, 2, 3, 4];
-    mem::forget(xs);
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile
deleted file mode 100644
index f578790..0000000
--- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
--include ../tools.mk
-
-# needs-sanitizer-support
-# only-linux
-# only-x86_64
-
-all:
-	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan
-	$(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value
-	$(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) librustc_msan
-	$(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs
deleted file mode 100644
index a9ae85f..0000000
--- a/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use std::mem::MaybeUninit;
-
-fn main() {
-    // This is technically not sound -- but we're literally trying to test
-    // that the sanitizer catches this, so I guess "intentionally unsound"?
-    let xs: [u8; 4] = unsafe { MaybeUninit::uninit().assume_init() };
-    let y = xs[0] + xs[1];
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs
deleted file mode 100644
index eae5250..0000000
--- a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    // This is technically not sound -- but we're literally trying to test
-    // that the sanitizer catches this, so I guess "intentionally unsound"?
-    #[allow(deprecated)]
-    let xs: [u8; 4] = unsafe { std::mem::uninitialized() };
-    let y = xs[0] + xs[1];
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c
index a6d3bcd..735e2b1 100644
--- a/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c
+++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c
@@ -1,4 +1,3 @@
-// ignore-license
 void overflow();
 
 int main() {
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/Makefile b/src/test/run-make-fulldeps/share-generics-dylib/Makefile
new file mode 100644
index 0000000..c6b5efc
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/Makefile
@@ -0,0 +1,22 @@
+# This test makes sure all generic instances get re-exported from Rust dylibs for use by
+# `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`)
+# which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is
+# supposed to re-export both these instances, and then there are `instance_user_a_rlib` and
+# `instance_user_b_rlib` which each rely on a specific instance to be available.
+#
+# In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does
+# not export both then we'll get an `undefined reference` error for one of the instances.
+#
+# This is regression test for https://github.com/rust-lang/rust/issues/67276.
+
+-include ../../run-make-fulldeps/tools.mk
+
+COMMON_ARGS=-Cprefer-dynamic -Zshare-generics=yes -Ccodegen-units=1 -Zsymbol-mangling-version=v0
+
+all:
+	$(RUSTC) instance_provider_a.rs $(COMMON_ARGS) --crate-type=rlib
+	$(RUSTC) instance_provider_b.rs $(COMMON_ARGS) --crate-type=rlib
+	$(RUSTC) instance_user_dylib.rs $(COMMON_ARGS) --crate-type=dylib
+	$(RUSTC) instance_user_a_rlib.rs $(COMMON_ARGS) --crate-type=rlib
+	$(RUSTC) instance_user_b_rlib.rs $(COMMON_ARGS) --crate-type=rlib
+	$(RUSTC) linked_leaf.rs $(COMMON_ARGS) --crate-type=bin
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs
new file mode 100644
index 0000000..b4e125a
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs
@@ -0,0 +1,6 @@
+use std::cell::Cell;
+
+pub fn foo() {
+    let a: Cell<i32> = Cell::new(1);
+    a.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs
new file mode 100644
index 0000000..f613db8
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs
@@ -0,0 +1,6 @@
+use std::cell::Cell;
+
+pub fn foo() {
+    let b: Cell<i32> = Cell::new(1);
+    b.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs
new file mode 100644
index 0000000..c8e6ab9
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs
@@ -0,0 +1,9 @@
+extern crate instance_provider_a as upstream;
+use std::cell::Cell;
+
+pub fn foo() {
+    upstream::foo();
+
+    let b: Cell<i32> = Cell::new(1);
+    b.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs
new file mode 100644
index 0000000..7c34af6
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs
@@ -0,0 +1,9 @@
+extern crate instance_provider_b as upstream;
+use std::cell::Cell;
+
+pub fn foo() {
+    upstream::foo();
+
+    let b: Cell<i32> = Cell::new(1);
+    b.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs
new file mode 100644
index 0000000..7c8368e
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs
@@ -0,0 +1,7 @@
+extern crate instance_provider_a;
+extern crate instance_provider_b;
+
+pub fn foo() {
+    instance_provider_a::foo();
+    instance_provider_b::foo();
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs
new file mode 100644
index 0000000..e510dad
--- /dev/null
+++ b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs
@@ -0,0 +1,15 @@
+extern crate instance_user_dylib;
+extern crate instance_user_a_rlib;
+extern crate instance_user_b_rlib;
+
+use std::cell::Cell;
+
+fn main() {
+
+    instance_user_a_rlib::foo();
+    instance_user_b_rlib::foo();
+    instance_user_dylib::foo();
+
+    let a: Cell<i32> = Cell::new(1);
+    a.set(123);
+}
diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs
index 75d95a4..c63fe4d 100644
--- a/src/test/run-make-fulldeps/simd-ffi/simd.rs
+++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs
@@ -4,35 +4,28 @@
 // cross-compiled standard libraries.
 #![feature(no_core, optin_builtin_traits)]
 #![no_core]
-
 #![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
 
-
-#[repr(C)]
 #[derive(Copy)]
 #[repr(simd)]
 pub struct f32x4(f32, f32, f32, f32);
 
-
-extern {
+extern "C" {
     #[link_name = "llvm.sqrt.v4f32"]
     fn vsqrt(x: f32x4) -> f32x4;
 }
 
 pub fn foo(x: f32x4) -> f32x4 {
-    unsafe {vsqrt(x)}
+    unsafe { vsqrt(x) }
 }
 
-#[repr(C)]
 #[derive(Copy)]
 #[repr(simd)]
 pub struct i32x4(i32, i32, i32, i32);
 
-
-extern {
+extern "C" {
     // _mm_sll_epi32
-    #[cfg(any(target_arch = "x86",
-              target_arch = "x86-64"))]
+    #[cfg(any(target_arch = "x86", target_arch = "x86-64"))]
     #[link_name = "llvm.x86.sse2.psll.d"]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 
@@ -48,22 +41,24 @@
     // just some substitute foreign symbol, not an LLVM intrinsic; so
     // we still get type checking, but not as detailed as (ab)using
     // LLVM.
-    #[cfg(not(any(target_arch = "x86",
-                  target_arch = "x86-64",
-                  target_arch = "arm",
-                  target_arch = "aarch64")))]
+    #[cfg(not(any(
+        target_arch = "x86",
+        target_arch = "x86-64",
+        target_arch = "arm",
+        target_arch = "aarch64"
+    )))]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 }
 
 pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
-    unsafe {integer(a, b)}
+    unsafe { integer(a, b) }
 }
 
 #[lang = "sized"]
-pub trait Sized { }
+pub trait Sized {}
 
 #[lang = "copy"]
-pub trait Copy { }
+pub trait Copy {}
 
 impl Copy for f32 {}
 impl Copy for i32 {}
@@ -77,4 +72,6 @@
 
 #[macro_export]
 #[rustc_builtin_macro]
-macro_rules! Copy { () => () }
+macro_rules! Copy {
+    () => {};
+}
diff --git a/src/test/run-make/thumb-none-cortex-m/Makefile b/src/test/run-make/thumb-none-cortex-m/Makefile
index 6791c8c..36e51bc 100644
--- a/src/test/run-make/thumb-none-cortex-m/Makefile
+++ b/src/test/run-make/thumb-none-cortex-m/Makefile
@@ -10,10 +10,7 @@
 # - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
 # - thumbv7m-none-eabi (Bare Cortex-M3)
 
-# only-thumbv6m-none-eabi
-# only-thumbv7em-none-eabi
-# only-thumbv7em-none-eabihf
-# only-thumbv7m-none-eabi
+# only-thumb
 
 # For cargo setting
 RUSTC := $(RUSTC_ORIGINAL)
@@ -27,7 +24,8 @@
 CRATE_URL := https://github.com/rust-embedded/cortex-m
 CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
 
-export RUSTFLAGS := --cap-lints=allow
+# Don't make lints fatal, but they need to at least warn or they break Cargo's target info parsing.
+export RUSTFLAGS := --cap-lints=warn
 
 all:
 	env
diff --git a/src/test/run-make/thumb-none-qemu/Makefile b/src/test/run-make/thumb-none-qemu/Makefile
index cb1ff85..ab8b90e 100644
--- a/src/test/run-make/thumb-none-qemu/Makefile
+++ b/src/test/run-make/thumb-none-qemu/Makefile
@@ -1,7 +1,6 @@
 -include ../../run-make-fulldeps/tools.mk
 
-# only-thumbv7m-none-eabi
-# only-thumbv6m-none-eabi
+# only-thumb
 
 # How to run this
 # $ ./x.py clean
diff --git a/src/test/run-make/thumb-none-qemu/example/.cargo/config b/src/test/run-make/thumb-none-qemu/example/.cargo/config
index 0d6b19c..8b30310 100644
--- a/src/test/run-make/thumb-none-qemu/example/.cargo/config
+++ b/src/test/run-make/thumb-none-qemu/example/.cargo/config
@@ -1,12 +1,26 @@
-[target.thumbv7m-none-eabi]
-# uncomment this to make `cargo run` execute programs on QEMU
+[target.thumbv6m-none-eabi]
+# FIXME: Should be Cortex-M0, but Qemu used by CI is too old
 runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
 
-[target.thumbv6m-none-eabi]
-# uncomment this to make `cargo run` execute programs on QEMU
-# For now, we use cortex-m3 instead of cortex-m0 which are not supported by QEMU
+[target.thumbv7m-none-eabi]
 runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
 
+[target.thumbv7em-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv7em-none-eabihf]
+runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.base-none-eabi]
+# FIXME: Should be the Cortex-M23, bt Qemu does not currently support it
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.main-none-eabi]
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.thumbv8m.main-none-eabihf]
+runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
 [target.'cfg(all(target_arch = "arm", target_os = "none"))']
 # uncomment ONE of these three option to make `cargo run` start a GDB session
 # which option to pick depends on your system
@@ -28,4 +42,4 @@
   # "-C", "linker=arm-none-eabi-gcc",
   # "-C", "link-arg=-Wl,-Tlink.x",
   # "-C", "link-arg=-nostartfiles",
-]
\ No newline at end of file
+]
diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.lock b/src/test/run-make/thumb-none-qemu/example/Cargo.lock
new file mode 100644
index 0000000..687b962
--- /dev/null
+++ b/src/test/run-make/thumb-none-qemu/example/Cargo.lock
@@ -0,0 +1,199 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aligned"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "as-slice 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "as-slice"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bare-metal"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-rt"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cortex-m-rt-macros 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-rt-macros"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cortex-m-semihosting"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "example"
+version = "0.1.0"
+dependencies = [
+ "cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cortex-m-rt 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "panic-halt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "r0"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "syn"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "typenum"
+version = "1.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "vcell"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "volatile-register"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum aligned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94"
+"checksum as-slice 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "be6b7e95ac49d753f19cab5a825dea99a1149a04e4e3230b33ae16e120954c04"
+"checksum bare-metal 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
+"checksum cortex-m 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2954942fbbdd49996704e6f048ce57567c3e1a4e2dc59b41ae9fde06a01fc763"
+"checksum cortex-m-rt 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "33a716cd7d8627fae3892c2eede9249e50d2d79aedfb43ca28dad9a2b23876d9"
+"checksum cortex-m-rt-macros 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "72b1073338d1e691b3b7aaf6bd61993e589ececce9242a02dfa5453e1b98918d"
+"checksum cortex-m-semihosting 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "113ef0ecffee2b62b58f9380f4469099b30e9f9cbee2804771b4203ba1762cfa"
+"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
+"checksum generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
+"checksum panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
+"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
+"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
+"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
+"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
+"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.toml b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
index 73fdee7..051d41b 100644
--- a/src/test/run-make/thumb-none-qemu/example/Cargo.toml
+++ b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
@@ -5,7 +5,7 @@
 edition = "2018"
 
 [dependencies]
-cortex-m = "0.5.4"
-cortex-m-rt = "=0.5.4"
+cortex-m = "0.6.2"
+cortex-m-rt = "0.6.11"
 panic-halt = "0.2.0"
 cortex-m-semihosting = "0.3.1"
diff --git a/src/test/run-make/thumb-none-qemu/example/src/main.rs b/src/test/run-make/thumb-none-qemu/example/src/main.rs
index 4a08419..2abfde8 100644
--- a/src/test/run-make/thumb-none-qemu/example/src/main.rs
+++ b/src/test/run-make/thumb-none-qemu/example/src/main.rs
@@ -1,4 +1,3 @@
-// #![feature(stdsimd)]
 #![no_main]
 #![no_std]
 use core::fmt::Write;
@@ -6,12 +5,9 @@
 use cortex_m_rt::entry;
 use cortex_m_semihosting as semihosting;
 
-//FIXME: This imports the provided #[panic_handler].
-#[allow(rust_2018_idioms)]
-extern crate panic_halt;
+use panic_halt as _;
 
-entry!(main);
-
+#[entry]
 fn main() -> ! {
     let x = 42;
 
diff --git a/src/test/run-make/wasm-export-all-symbols/bar.rs b/src/test/run-make/wasm-export-all-symbols/bar.rs
index c5de87e..ac9c20a 100644
--- a/src/test/run-make/wasm-export-all-symbols/bar.rs
+++ b/src/test/run-make/wasm-export-all-symbols/bar.rs
@@ -2,3 +2,6 @@
 
 #[no_mangle]
 pub extern fn foo() {}
+
+#[no_mangle]
+pub static FOO: u64 = 42;
diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js
index 7b6fc7a..72db335 100644
--- a/src/test/run-make/wasm-export-all-symbols/verify.js
+++ b/src/test/run-make/wasm-export-all-symbols/verify.js
@@ -9,16 +9,20 @@
 
 const my_exports = {};
 let nexports = 0;
+
 for (const entry of list) {
-  if (entry.kind !== 'function')
-    continue;
-  my_exports[entry.name] = true;
-  nexports += 1;
+  if (entry.kind == 'function'){
+    nexports += 1;
+  }
+  my_exports[entry.name] = entry.kind;
 }
 
-if (my_exports.foo === undefined)
+if (my_exports.foo != "function")
   throw new Error("`foo` wasn't defined");
 
+if (my_exports.FOO != "global")
+  throw new Error("`FOO` wasn't defined");
+
 if (my_exports.main === undefined) {
   if (nexports != 1)
     throw new Error("should only have one function export");
diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout
index 9887d07..ee79ae1 100644
--- a/src/test/rustdoc-ui/failed-doctest-output.stdout
+++ b/src/test/rustdoc-ui/failed-doctest-output.stdout
@@ -27,7 +27,7 @@
 stderr 1
 stderr 2
 thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:7:1
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 
 
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
index 34e92c4..72037dd 100644
--- a/src/test/rustdoc-ui/invalid-syntax.rs
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -93,3 +93,9 @@
 ///
 pub fn indent_after_fenced() {}
 //~^^^ WARNING could not parse code block as Rust code
+
+/// ```
+/// "invalid
+/// ```
+pub fn invalid() {}
+//~^^^^ WARNING could not parse code block as Rust code
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index 32cc207..a90d3bb 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -132,3 +132,18 @@
    |
    = note: error from rustc: unknown start of token: \
 
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:97:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | /// "invalid
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unterminated double quote string
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
diff --git a/src/test/rustdoc-ui/test-compile-fail1.rs b/src/test/rustdoc-ui/test-compile-fail1.rs
new file mode 100644
index 0000000..a053902
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail1.rs
@@ -0,0 +1,8 @@
+// compile-flags:--test
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-compile-fail1.stderr b/src/test/rustdoc-ui/test-compile-fail1.stderr
new file mode 100644
index 0000000..2b38ba9
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail1.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `f` is defined multiple times
+ --> $DIR/test-compile-fail1.rs:8:1
+  |
+6 | pub fn f() {}
+  | ---------- previous definition of the value `f` here
+7 | 
+8 | pub fn f() {}
+  | ^^^^^^^^^^ `f` redefined here
+  |
+  = note: `f` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/rustdoc-ui/test-compile-fail2.rs b/src/test/rustdoc-ui/test-compile-fail2.rs
new file mode 100644
index 0000000..651ded0
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail2.rs
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+fail
diff --git a/src/test/rustdoc-ui/test-compile-fail2.stderr b/src/test/rustdoc-ui/test-compile-fail2.stderr
new file mode 100644
index 0000000..cee5b63
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `<eof>`
+ --> $DIR/test-compile-fail2.rs:3:1
+  |
+3 | fail
+  | ^^^^ expected one of `!` or `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/test-compile-fail3.rs b/src/test/rustdoc-ui/test-compile-fail3.rs
new file mode 100644
index 0000000..faa30ad
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail3.rs
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+"fail
diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr
new file mode 100644
index 0000000..7a2f181
--- /dev/null
+++ b/src/test/rustdoc-ui/test-compile-fail3.stderr
@@ -0,0 +1,8 @@
+error: unterminated double quote string
+ --> $DIR/test-compile-fail3.rs:3:1
+  |
+3 | "fail
+  | ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/test-no_std.rs b/src/test/rustdoc-ui/test-no_std.rs
new file mode 100644
index 0000000..166a873
--- /dev/null
+++ b/src/test/rustdoc-ui/test-no_std.rs
@@ -0,0 +1,12 @@
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// build-pass
+
+#![no_std]
+
+extern crate alloc;
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-no_std.stdout b/src/test/rustdoc-ui/test-no_std.stdout
new file mode 100644
index 0000000..9cdcac2
--- /dev/null
+++ b/src/test/rustdoc-ui/test-no_std.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/test-no_std.rs - f (line 9) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs
index 5f9708a..5a03e82 100644
--- a/src/test/rustdoc/async-fn.rs
+++ b/src/test/rustdoc/async-fn.rs
@@ -15,6 +15,11 @@
     a
 }
 
+// @has async_fn/fn.qux.html '//pre[@class="rust fn"]' 'pub async unsafe fn qux() -> char'
+pub async unsafe fn qux() -> char {
+    '⚠'
+}
+
 trait Bar {}
 
 impl Bar for () {}
@@ -26,8 +31,10 @@
 
 // @has async_fn/struct.Foo.html
 // @matches - '//code' 'pub async fn f\(\)$'
+// @matches - '//code' 'pub async unsafe fn g\(\)$'
 pub struct Foo;
 
 impl Foo {
     pub async fn f() {}
+    pub async unsafe fn g() {}
 }
diff --git a/src/test/rustdoc/auto_aliases.rs b/src/test/rustdoc/auto_aliases.rs
new file mode 100644
index 0000000..7b52a69
--- /dev/null
+++ b/src/test/rustdoc/auto_aliases.rs
@@ -0,0 +1,6 @@
+#![feature(optin_builtin_traits)]
+
+// @has auto_aliases/trait.Bar.html '//h3[@aliases="auto_aliases::Foo"]' 'impl Bar for Foo'
+pub struct Foo;
+
+pub auto trait Bar {}
diff --git a/src/test/rustdoc/bad-codeblock-syntax.rs b/src/test/rustdoc/bad-codeblock-syntax.rs
index 0ab2f68..afef86e 100644
--- a/src/test/rustdoc/bad-codeblock-syntax.rs
+++ b/src/test/rustdoc/bad-codeblock-syntax.rs
@@ -25,3 +25,18 @@
 /// \_
 /// ```
 pub fn ok() {}
+
+// @has bad_codeblock_syntax/fn.escape.html
+// @has - '//*[@class="docblock"]/pre/code' '\_ <script>alert("not valid Rust");</script>'
+/// ```
+/// \_
+/// <script>alert("not valid Rust");</script>
+/// ```
+pub fn escape() {}
+
+// @has bad_codeblock_syntax/fn.unterminated.html
+// @has - '//*[@class="docblock"]/pre/code' '"unterminated'
+/// ```
+/// "unterminated
+/// ```
+pub fn unterminated() {}
diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs
index ed45d33..54bdd76 100644
--- a/src/test/rustdoc/const-generics/add-impl.rs
+++ b/src/test/rustdoc/const-generics/add-impl.rs
@@ -11,7 +11,7 @@
     inner: T,
 }
 
-// @has foo/struct.Simd.html '//div[@id="implementations-list"]/h3/code' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
+// @has foo/struct.Simd.html '//div[@id="implementations-list"]/h3/code' 'impl Add<Simd<u8, 16usize>> for Simd<u8, 16>'
 impl Add for Simd<u8, 16> {
     type Output = Self;
 
diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
new file mode 100644
index 0000000..770f8d7
--- /dev/null
+++ b/src/test/rustdoc/deref-typedef.rs
@@ -0,0 +1,33 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Bar.html'
+// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
+// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooC>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
+
+pub struct FooA;
+pub type FooB = FooA;
+pub type FooC = FooB;
+
+impl FooA {
+    pub fn foo_a(&self) {}
+}
+
+impl FooB {
+    pub fn foo_b(&self) {}
+}
+
+impl FooC {
+    pub fn foo_c(&self) {}
+}
+
+pub struct Bar;
+impl std::ops::Deref for Bar {
+    type Target = FooC;
+    fn deref(&self) -> &Self::Target { unimplemented!() }
+}
diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs
index 505d6ee..9ccc5d7 100644
--- a/src/test/rustdoc/duplicate-cfg.rs
+++ b/src/test/rustdoc/duplicate-cfg.rs
@@ -1,15 +1,42 @@
+// ignore-tidy-linelength
+
 #![crate_name = "foo"]
 #![feature(doc_cfg)]
 
-// @has 'foo/index.html'
-// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and'
-// @has '-' '//*[@class="stab portability"]' 'feature="sync"'
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.'
 #[doc(cfg(feature = "sync"))]
 #[doc(cfg(feature = "sync"))]
 pub struct Foo;
 
+// @has 'foo/bar/struct.Bar.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.'
 #[doc(cfg(feature = "sync"))]
 pub mod bar {
     #[doc(cfg(feature = "sync"))]
     pub struct Bar;
 }
+
+// @has 'foo/baz/struct.Baz.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.'
+#[doc(cfg(all(feature = "sync", feature = "send")))]
+pub mod baz {
+    #[doc(cfg(feature = "sync"))]
+    pub struct Baz;
+}
+
+// @has 'foo/qux/struct.Qux.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.'
+#[doc(cfg(feature = "sync"))]
+pub mod qux {
+    #[doc(cfg(all(feature = "sync", feature = "send")))]
+    pub struct Qux;
+}
+
+// @has 'foo/quux/struct.Quux.html'
+// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" and foo and bar only.'
+#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
+pub mod quux {
+    #[doc(cfg(all(feature = "send", feature = "sync", bar)))]
+    pub struct Quux;
+}
diff --git a/src/test/rustdoc/issue-46380.rs b/src/test/rustdoc/issue-46380.rs
deleted file mode 100644
index 8837a6b..0000000
--- a/src/test/rustdoc/issue-46380.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags: --document-private-items
-
-// @has issue_46380/struct.Hidden.html
-#[doc(hidden)]
-pub struct Hidden;
diff --git a/src/test/rustdoc/issue-67851-both.rs b/src/test/rustdoc/issue-67851-both.rs
new file mode 100644
index 0000000..d69b943
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-both.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Zunstable-options --document-private-items --document-hidden-items
+
+// @has issue_67851_both/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has issue_67851_both/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/issue-67851-hidden.rs b/src/test/rustdoc/issue-67851-hidden.rs
new file mode 100644
index 0000000..8a3cafe
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-hidden.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Zunstable-options --document-hidden-items
+
+// @has issue_67851_hidden/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has issue_67851_hidden/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/issue-67851-neither.rs b/src/test/rustdoc/issue-67851-neither.rs
new file mode 100644
index 0000000..4e3cd83
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-neither.rs
@@ -0,0 +1,6 @@
+// @!has issue_67851_neither/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has issue_67851_neither/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/issue-67851-private.rs b/src/test/rustdoc/issue-67851-private.rs
new file mode 100644
index 0000000..8addc7f
--- /dev/null
+++ b/src/test/rustdoc/issue-67851-private.rs
@@ -0,0 +1,8 @@
+// compile-flags: --document-private-items
+
+// @!has issue_67851_private/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has issue_67851_private/struct.Private.html
+struct Private;
diff --git a/src/test/rustdoc/remove-url-from-headings.rs b/src/test/rustdoc/remove-url-from-headings.rs
new file mode 100644
index 0000000..9761c1d
--- /dev/null
+++ b/src/test/rustdoc/remove-url-from-headings.rs
@@ -0,0 +1,17 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// !@has - '//a[@href="http://a.a"]'
+// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
+// @has - '//a[@href="#another-one-urg"]' 'Another one urg'
+
+/// fooo
+///
+/// # Implementing [stuff](http://a.a "title") somewhere
+///
+/// hello
+///
+/// # Another [one][two] urg
+///
+/// [two]: http://a.a
+pub fn foo() {}
diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index ee14d71..725c350 100644
--- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -1,17 +1,17 @@
 #![feature(box_syntax, plugin, plugin_registrar, rustc_private)]
 #![crate_type = "dylib"]
 
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
 extern crate rustc_hir;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 extern crate rustc_span;
 extern crate syntax;
 
-use rustc::hir::intravisit;
+use rustc_hir::intravisit;
 use rustc_hir as hir;
 use rustc_hir::Node;
-use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
 use rustc_driver::plugin::Registry;
 use rustc_span::source_map;
 use syntax::print::pprust;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
index 4ccbe8a..98963a1 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
@@ -2,14 +2,14 @@
 
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
 extern crate rustc_hir;
 extern crate rustc_span;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 extern crate syntax;
 
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass};
+use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass};
 use rustc_driver::plugin::Registry;
 use rustc_span::symbol::Symbol;
 use syntax::attr;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 360bffa..589477d 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -3,14 +3,14 @@
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
 
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
 extern crate rustc_hir;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 extern crate rustc_span;
 extern crate syntax;
 
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray};
+use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray};
 use rustc_driver::plugin::Registry;
 use rustc_span::symbol::Symbol;
 use syntax::attr;
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index 786c699..2cc288c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -4,12 +4,12 @@
 #![feature(box_syntax, rustc_private)]
 
 // Load rustc as a plugin to get macros.
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
 extern crate rustc_hir;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId};
+use rustc_lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId};
 use rustc_driver::plugin::Registry;
 
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index bb96dba..c704701 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -6,11 +6,11 @@
 extern crate syntax;
 
 // Load rustc as a plugin to get macros
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 
-use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
+use rustc_lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
 use rustc_driver::plugin::Registry;
 use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index 1704909..fa545dd 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -4,11 +4,11 @@
 extern crate syntax;
 
 // Load rustc as a plugin to get macros
-#[macro_use] extern crate rustc;
-#[macro_use] extern crate rustc_session;
 extern crate rustc_driver;
+#[macro_use] extern crate rustc_lint;
+#[macro_use] extern crate rustc_session;
 
-use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
 use rustc_driver::plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
index 7ce2a1d..8d9cbe4 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
@@ -6,9 +6,8 @@
 extern crate rustc;
 extern crate rustc_session;
 
-use rustc::lint::{LintArray, LintPass};
-use rustc::{declare_lint_pass, impl_lint_pass};
-use rustc_session::declare_lint;
+use rustc_session::lint::{LintArray, LintPass};
+use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 
 declare_lint! {
     pub TEST_LINT,
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
index ad8670c..39ac001 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
@@ -1,5 +1,5 @@
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:21:6
+  --> $DIR/lint_pass_impl_without_macro.rs:20:6
    |
 LL | impl LintPass for Foo {
    |      ^^^^^^^^
@@ -12,7 +12,7 @@
    = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:31:14
+  --> $DIR/lint_pass_impl_without_macro.rs:30:14
    |
 LL |         impl LintPass for Custom {
    |              ^^^^^^^^
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs
index 569f04d..35ddab9 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.rs
@@ -10,6 +10,8 @@
 
 #[allow(test_lint)]
 //~^ ERROR allow(test_lint) overruled by outer forbid(test_lint)
+//~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
+//~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
 pub fn main() {
     lintme();
 }
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
index c0de1fe..f93a0a0 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
@@ -7,6 +7,15 @@
 LL | #[allow(test_lint)]
    |         ^^^^^^^^^ overruled by previous forbid
 
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-attrs.rs:11:9
+   |
+LL | #![forbid(test_lint)]
+   |           --------- `forbid` level set here
+...
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-plugin-forbid-attrs.rs:5:1
    |
@@ -27,6 +36,15 @@
 LL | #![forbid(test_lint)]
    |           ^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-attrs.rs:11:9
+   |
+LL | #![forbid(test_lint)]
+   |           --------- `forbid` level set here
+...
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs
index 82313f6..695d3ae 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.rs
@@ -8,6 +8,8 @@
 fn lintme() { } //~ ERROR item is named 'lintme'
 
 #[allow(test_lint)] //~ ERROR allow(test_lint) overruled by outer forbid(test_lint)
+                    //~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
+                    //~| ERROR allow(test_lint) overruled by outer forbid(test_lint)
 pub fn main() {
     lintme();
 }
diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
index f189efb..0302ec8 100644
--- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
@@ -6,6 +6,14 @@
    |
    = note: `forbid` lint level was set on command line
 
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-cmdline.rs:10:9
+   |
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-plugin-forbid-cmdline.rs:6:1
    |
@@ -22,6 +30,14 @@
    |
    = note: requested on the command line with `-F test-lint`
 
-error: aborting due to 2 previous errors
+error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
+  --> $DIR/lint-plugin-forbid-cmdline.rs:10:9
+   |
+LL | #[allow(test_lint)]
+   |         ^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr
index 825a341..2f1c29e 100644
--- a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr
+++ b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr
@@ -2,6 +2,10 @@
    |
    = note: requested on the command line with `-A test_lint`
 
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-tool-cmdline-allow.rs:7:1
    |
@@ -10,6 +14,10 @@
    |
    = note: `#[warn(deprecated)]` on by default
 
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
 warning: item is named 'lintme'
   --> $DIR/lint-tool-cmdline-allow.rs:9:1
    |
@@ -18,3 +26,7 @@
    |
    = note: `#[warn(clippy::test_lint)]` on by default
 
+warning: lint name `test_lint` is deprecated and does not have an effect anymore. Use: clippy::test_lint
+   |
+   = note: requested on the command line with `-A test_lint`
+
diff --git a/src/test/ui-fulldeps/lint-tool-test.rs b/src/test/ui-fulldeps/lint-tool-test.rs
index 216a8cb..f92bcd2 100644
--- a/src/test/ui-fulldeps/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/lint-tool-test.rs
@@ -8,9 +8,12 @@
 #![allow(dead_code)]
 #![cfg_attr(foo, warn(test_lint))]
 //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
-//~^^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 #![deny(clippy_group)]
 //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
@@ -25,6 +28,8 @@
 
 #[allow(test_group)]
 //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
 fn hello() {
     fn lintmetoo() { }
diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr
index d4031a7..809b9ac 100644
--- a/src/test/ui-fulldeps/lint-tool-test.stderr
+++ b/src/test/ui-fulldeps/lint-tool-test.stderr
@@ -7,19 +7,19 @@
    = note: `#[warn(renamed_and_removed_lints)]` on by default
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
-  --> $DIR/lint-tool-test.rs:12:9
+  --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
-  --> $DIR/lint-tool-test.rs:26:9
+  --> $DIR/lint-tool-test.rs:29:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
 warning: unknown lint: `this_lint_does_not_exist`
-  --> $DIR/lint-tool-test.rs:28:8
+  --> $DIR/lint-tool-test.rs:33:8
    |
 LL | #[deny(this_lint_does_not_exist)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,6 +32,18 @@
 LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:13:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:29:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-tool-test.rs:6:1
    |
@@ -40,31 +52,49 @@
    |
    = note: `#[warn(deprecated)]` on by default
 
+warning: lint name `test_lint` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:9:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:13:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
 error: item is named 'lintme'
-  --> $DIR/lint-tool-test.rs:15:1
+  --> $DIR/lint-tool-test.rs:18:1
    |
 LL | fn lintme() { }
    | ^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-tool-test.rs:12:9
+  --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]`
 
 error: item is named 'lintmetoo'
-  --> $DIR/lint-tool-test.rs:23:5
+  --> $DIR/lint-tool-test.rs:26:5
    |
 LL |     fn lintmetoo() { }
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-tool-test.rs:12:9
+  --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]`
 
+warning: lint name `test_group` is deprecated and may not have an effect in the future. Also `cfg_attr(cargo-clippy)` won't be necessary anymore
+  --> $DIR/lint-tool-test.rs:29:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/anon-params-deprecated.stderr b/src/test/ui/anon-params-deprecated.stderr
index e97dbc1..8e4fa70 100644
--- a/src/test/ui/anon-params-deprecated.stderr
+++ b/src/test/ui/anon-params-deprecated.stderr
@@ -2,7 +2,7 @@
   --> $DIR/anon-params-deprecated.rs:9:12
    |
 LL |     fn foo(i32);
-   |            ^^^ help: Try naming the parameter or explicitly ignoring it: `_: i32`
+   |            ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32`
    |
 note: lint level defined here
   --> $DIR/anon-params-deprecated.rs:1:9
@@ -16,7 +16,7 @@
   --> $DIR/anon-params-deprecated.rs:12:30
    |
 LL |     fn bar_with_default_impl(String, String) {}
-   |                              ^^^^^^ help: Try naming the parameter or explicitly ignoring it: `_: String`
+   |                              ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
@@ -25,7 +25,7 @@
   --> $DIR/anon-params-deprecated.rs:12:38
    |
 LL |     fn bar_with_default_impl(String, String) {}
-   |                                      ^^^^^^ help: Try naming the parameter or explicitly ignoring it: `_: String`
+   |                                      ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
diff --git a/src/test/ui/match/match-vec-mismatch.rs b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs
similarity index 95%
rename from src/test/ui/match/match-vec-mismatch.rs
rename to src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs
index a0ef927..34adb42 100644
--- a/src/test/ui/match/match-vec-mismatch.rs
+++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     match "foo".to_string() {
         ['f', 'o', ..] => {}
diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr
similarity index 80%
rename from src/test/ui/match/match-vec-mismatch.stderr
rename to src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr
index a3523bb..c454814 100644
--- a/src/test/ui/match/match-vec-mismatch.stderr
+++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr
@@ -1,29 +1,29 @@
 error[E0425]: cannot find value `does_not_exist` in this scope
-  --> $DIR/match-vec-mismatch.rs:28:11
+  --> $DIR/slice-pat-type-mismatches.rs:26:11
    |
 LL |     match does_not_exist {
    |           ^^^^^^^^^^^^^^ not found in this scope
 
 error[E0529]: expected an array or slice, found `std::string::String`
-  --> $DIR/match-vec-mismatch.rs:5:9
+  --> $DIR/slice-pat-type-mismatches.rs:3:9
    |
 LL |         ['f', 'o', ..] => {}
    |         ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String`
 
 error[E0527]: pattern requires 1 element but array has 3
-  --> $DIR/match-vec-mismatch.rs:20:9
+  --> $DIR/slice-pat-type-mismatches.rs:18:9
    |
 LL |         [0] => {},
    |         ^^^ expected 3 elements
 
 error[E0528]: pattern requires at least 4 elements but array has 3
-  --> $DIR/match-vec-mismatch.rs:25:9
+  --> $DIR/slice-pat-type-mismatches.rs:23:9
    |
 LL |         [0, 1, 2, 3, x @ ..] => {}
    |         ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
 
 error[E0282]: type annotations needed
-  --> $DIR/match-vec-mismatch.rs:36:9
+  --> $DIR/slice-pat-type-mismatches.rs:34:9
    |
 LL |         [] => {}
    |         ^^ cannot infer type
diff --git a/src/test/ui/parser/match-vec-invalid.rs b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs
similarity index 75%
rename from src/test/ui/parser/match-vec-invalid.rs
rename to src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs
index 00f4374..97e3362 100644
--- a/src/test/ui/parser/match-vec-invalid.rs
+++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs
@@ -3,8 +3,6 @@
     match a {
         [1, tail @ .., tail @ ..] => {},
         //~^ ERROR identifier `tail` is bound more than once in the same pattern
-        //~| ERROR subslice patterns are unstable
-        //~| ERROR subslice patterns are unstable
         //~| ERROR `..` can only be used once per slice pattern
         _ => ()
     }
diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr
new file mode 100644
index 0000000..4d60787
--- /dev/null
+++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr
@@ -0,0 +1,24 @@
+error[E0416]: identifier `tail` is bound more than once in the same pattern
+  --> $DIR/subslice-only-once-semantic-restriction.rs:4:24
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                        ^^^^ used in a pattern more than once
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/subslice-only-once-semantic-restriction.rs:4:31
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                    --         ^^ can only be used once per slice pattern
+   |                    |
+   |                    previously used here
+
+error[E0308]: mismatched types
+  --> $DIR/subslice-only-once-semantic-restriction.rs:11:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected `()`, found integer
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0416.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
index 0e767d9..69c3392 100644
--- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
+++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
@@ -2,7 +2,7 @@
 
 // run-pass
 
-#![feature(slice_patterns, const_fn, const_if_match)]
+#![feature(const_fn, const_if_match)]
 #[derive(PartialEq, Debug, Clone)]
 struct N(u8);
 
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
index 5444f8a..0b793fa 100644
--- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
+++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
@@ -2,8 +2,6 @@
 
 // run-pass
 
-#![feature(slice_patterns)]
-
 #[derive(PartialEq, Debug, Clone)]
 struct N(u8);
 
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-pass.rs b/src/test/ui/array-slice-vec/subslice-patterns-pass.rs
index 1ebf3de..e0579091 100644
--- a/src/test/ui/array-slice-vec/subslice-patterns-pass.rs
+++ b/src/test/ui/array-slice-vec/subslice-patterns-pass.rs
@@ -4,8 +4,6 @@
 
 // run-pass
 
-#![feature(slice_patterns)]
-
 #![allow(unreachable_patterns)]
 
 use std::convert::identity;
diff --git a/src/test/ui/array-slice-vec/vec-matching-fixed.rs b/src/test/ui/array-slice-vec/vec-matching-fixed.rs
index 5253bc1..fdeb7e4 100644
--- a/src/test/ui/array-slice-vec/vec-matching-fixed.rs
+++ b/src/test/ui/array-slice-vec/vec-matching-fixed.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 fn a() {
     let x = [1, 2, 3];
     match x {
diff --git a/src/test/ui/array-slice-vec/vec-matching-fold.rs b/src/test/ui/array-slice-vec/vec-matching-fold.rs
index f416160..9988992 100644
--- a/src/test/ui/array-slice-vec/vec-matching-fold.rs
+++ b/src/test/ui/array-slice-vec/vec-matching-fold.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 use std::fmt::Debug;
 
 fn foldl<T, U, F>(values: &[T],
diff --git a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
index f0602c3..ed34f07 100644
--- a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
+++ b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
@@ -1,7 +1,6 @@
 // run-pass
-#![allow(unused_variables)]
 
-#![feature(slice_patterns)]
+#![allow(unused_variables)]
 
 pub fn main() {
     let x = &[1, 2, 3, 4, 5];
diff --git a/src/test/ui/array-slice-vec/vec-matching.rs b/src/test/ui/array-slice-vec/vec-matching.rs
index 49c736b..7009244 100644
--- a/src/test/ui/array-slice-vec/vec-matching.rs
+++ b/src/test/ui/array-slice-vec/vec-matching.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 fn a() {
     let x = [1];
     match x {
diff --git a/src/test/ui/array-slice-vec/vec-tail-matching.rs b/src/test/ui/array-slice-vec/vec-tail-matching.rs
index 3c7b160..5f16992 100644
--- a/src/test/ui/array-slice-vec/vec-tail-matching.rs
+++ b/src/test/ui/array-slice-vec/vec-tail-matching.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 struct Foo {
     string: &'static str
 }
diff --git a/src/test/ui/associated-const/associated-const-no-item.rs b/src/test/ui/associated-const/associated-const-no-item.rs
index 35fb662f..024d14e 100644
--- a/src/test/ui/associated-const/associated-const-no-item.rs
+++ b/src/test/ui/associated-const/associated-const-no-item.rs
@@ -3,7 +3,7 @@
 }
 
 const X: i32 = <i32>::ID;
-//~^ ERROR no associated item named `ID` found for type `i32`
+//~^ ERROR no associated item named `ID` found
 
 fn main() {
     assert_eq!(1, X);
diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr
index 23916a3..3a70e7d 100644
--- a/src/test/ui/associated-const/issue-63496.stderr
+++ b/src/test/ui/associated-const/issue-63496.stderr
@@ -5,9 +5,13 @@
    |     --------------- required by `A::C`
 LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                     ^^^^ cannot infer type
+   |                     ^^^^
+   |                     |
+   |                     cannot infer type
+   |                     help: use the fully qualified path to an implementation: `<Type as A>::C`
    |
    = note: cannot resolve `_: A`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error[E0283]: type annotations needed
   --> $DIR/issue-63496.rs:4:33
@@ -16,9 +20,13 @@
    |     --------------- required by `A::C`
 LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                                 ^^^^ cannot infer type
+   |                                 ^^^^
+   |                                 |
+   |                                 cannot infer type
+   |                                 help: use the fully qualified path to an implementation: `<Type as A>::C`
    |
    = note: cannot resolve `_: A`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr
index 5a62b97..6f89530 100644
--- a/src/test/ui/associated-item/associated-item-enum.stderr
+++ b/src/test/ui/associated-item/associated-item-enum.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `mispellable` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `mispellable` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:17:11
    |
 LL | enum Enum { Variant }
@@ -10,7 +10,7 @@
    |           variant or associated item not found in `Enum`
    |           help: there is a method with a similar name: `misspellable`
 
-error[E0599]: no variant or associated item named `mispellable_trait` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:18:11
    |
 LL | enum Enum { Variant }
@@ -19,7 +19,7 @@
 LL |     Enum::mispellable_trait();
    |           ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum`
 
-error[E0599]: no variant or associated item named `MISPELLABLE` found for type `Enum` in the current scope
+error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:19:11
    |
 LL | enum Enum { Variant }
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 9c825d5..ddabd55 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -13,9 +13,13 @@
 LL |     const X: usize;
    |     --------------- required by `Bar::X`
 LL |     fn return_n(&self) -> [u8; Bar::X];
-   |                                ^^^^^^ cannot infer type
+   |                                ^^^^^^
+   |                                |
+   |                                cannot infer type
+   |                                help: use the fully qualified path to an implementation: `<Type as Bar>::X`
    |
    = note: cannot resolve `_: Bar`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs
index 64bc9ee..65ca017 100644
--- a/src/test/ui/associated-type-bounds/duplicate.rs
+++ b/src/test/ui/associated-type-bounds/duplicate.rs
@@ -157,10 +157,13 @@
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
+//~| ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
+//~| ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
+//~| ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr
index caecc5e..defa629 100644
--- a/src/test/ui/associated-type-bounds/duplicate.stderr
+++ b/src/test/ui/associated-type-bounds/duplicate.stderr
@@ -531,7 +531,15 @@
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:160:46
+  --> $DIR/duplicate.rs:158:46
+   |
+LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
+   |                                  ----------  ^^^^^^^^^^ re-bound here
+   |                                  |
+   |                                  `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:161:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -539,7 +547,15 @@
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:162:49
+  --> $DIR/duplicate.rs:161:46
+   |
+LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
+   |                                  ----------  ^^^^^^^^^^ re-bound here
+   |                                  |
+   |                                  `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:164:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -547,7 +563,15 @@
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:164:43
+  --> $DIR/duplicate.rs:164:49
+   |
+LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
+   |                                  -------------  ^^^^^^^^^^^^^ re-bound here
+   |                                  |
+   |                                  `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:167:43
    |
 LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -555,7 +579,7 @@
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:166:43
+  --> $DIR/duplicate.rs:169:43
    |
 LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -563,7 +587,7 @@
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:168:46
+  --> $DIR/duplicate.rs:171:46
    |
 LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -571,7 +595,7 @@
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:171:40
+  --> $DIR/duplicate.rs:174:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -579,7 +603,7 @@
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:175:44
+  --> $DIR/duplicate.rs:178:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -587,7 +611,7 @@
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:179:43
+  --> $DIR/duplicate.rs:182:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -667,40 +691,40 @@
    |                                           ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:171:28
+  --> $DIR/duplicate.rs:174:28
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:171:40
+  --> $DIR/duplicate.rs:174:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:175:32
+  --> $DIR/duplicate.rs:178:32
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:175:44
+  --> $DIR/duplicate.rs:178:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:179:28
+  --> $DIR/duplicate.rs:182:28
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:179:43
+  --> $DIR/duplicate.rs:182:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                                           ^^^^^^^^^^^^^
 
-error: aborting due to 93 previous errors
+error: aborting due to 96 previous errors
 
diff --git a/src/test/ui/associated-types/issue-64848.rs b/src/test/ui/associated-types/issue-64848.rs
new file mode 100644
index 0000000..7771216
--- /dev/null
+++ b/src/test/ui/associated-types/issue-64848.rs
@@ -0,0 +1,29 @@
+// build-pass
+
+trait AssociatedConstant {
+    const DATA: ();
+}
+
+impl<F, T> AssociatedConstant for F
+where
+    F: FnOnce() -> T,
+    T: AssociatedConstant,
+{
+    const DATA: () = T::DATA;
+}
+
+impl AssociatedConstant for () {
+    const DATA: () = ();
+}
+
+fn foo() -> impl AssociatedConstant {
+    ()
+}
+
+fn get_data<T: AssociatedConstant>(_: T) -> &'static () {
+    &T::DATA
+}
+
+fn main() {
+    get_data(foo);
+}
diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs
index 645c903..ceeebbc 100644
--- a/src/test/ui/async-await/async-fn-nonsend.rs
+++ b/src/test/ui/async-await/async-fn-nonsend.rs
@@ -2,15 +2,15 @@
 // edition:2018
 // compile-flags: --crate-type lib
 
-use std::{
-    cell::RefCell,
-    fmt::Debug,
-    rc::Rc,
-};
+use std::{cell::RefCell, fmt::Debug, rc::Rc};
 
-fn non_sync() -> impl Debug { RefCell::new(()) }
+fn non_sync() -> impl Debug {
+    RefCell::new(())
+}
 
-fn non_send() -> impl Debug { Rc::new(()) }
+fn non_send() -> impl Debug {
+    Rc::new(())
+}
 
 fn take_ref<T>(_: &T) {}
 
@@ -53,5 +53,4 @@
     //~^ ERROR future cannot be sent between threads safely
     assert_send(non_sync_with_method_call());
     //~^ ERROR future cannot be sent between threads safely
-    //~^^ ERROR future cannot be sent between threads safely
 }
diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr
index 5c870ca..105fd23 100644
--- a/src/test/ui/async-await/async-fn-nonsend.stderr
+++ b/src/test/ui/async-await/async-fn-nonsend.stderr
@@ -62,27 +62,5 @@
 LL | }
    | - `f` is later dropped here
 
-error: future cannot be sent between threads safely
-  --> $DIR/async-fn-nonsend.rs:54:5
-   |
-LL | fn assert_send(_: impl Send) {}
-   |    -----------         ---- required by this bound in `assert_send`
-...
-LL |     assert_send(non_sync_with_method_call());
-   |     ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
-   |
-   = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
-note: future is not `Send` as this value is used across an await
-  --> $DIR/async-fn-nonsend.rs:43:9
-   |
-LL |     let f: &mut std::fmt::Formatter = panic!();
-   |         - has type `&mut std::fmt::Formatter<'_>`
-LL |     if non_sync().fmt(f).unwrap() == () {
-LL |         fut().await;
-   |         ^^^^^^^^^^^ await occurs here, with `f` maybe used later
-LL |     }
-LL | }
-   | - `f` is later dropped here
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr
index 239f801..dc3a475 100644
--- a/src/test/ui/async-await/dont-suggest-missing-await.stderr
+++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/dont-suggest-missing-await.rs:14:18
    |
+LL | async fn make_u32() -> u32 {
+   |                        --- the `Output` of this `async fn`'s found opaque type
+...
 LL |         take_u32(x)
    |                  ^ expected `u32`, found opaque type
    |
diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr
index 155c5cc..d682817 100644
--- a/src/test/ui/async-await/issue-64130-3-other.stderr
+++ b/src/test/ui/async-await/issue-64130-3-other.stderr
@@ -3,6 +3,9 @@
    |
 LL | fn is_qux<T: Qux>(t: T) { }
    |    ------    --- required by this bound in `is_qux`
+LL | 
+LL | async fn bar() {
+   |                - within this `impl std::future::Future`
 ...
 LL |     is_qux(bar());
    |     ^^^^^^ within `impl std::future::Future`, the trait `Qux` is not implemented for `Foo`
diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr
index ddbb469..1e52d74 100644
--- a/src/test/ui/async-await/issue-64130-4-async-move.stderr
+++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr
@@ -1,8 +1,17 @@
 error: future cannot be sent between threads safely
   --> $DIR/issue-64130-4-async-move.rs:15:17
    |
-LL | pub fn foo() -> impl Future + Send {
-   |                 ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+LL |   pub fn foo() -> impl Future + Send {
+   |                   ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+...
+LL | /     async move {
+LL | |         match client.status() {
+LL | |             200 => {
+LL | |                 let _x = get().await;
+...  |
+LL | |         }
+LL | |     }
+   | |_____- this returned value is of type `impl std::future::Future`
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)`
 note: future is not `Send` as this value is used across an await
@@ -16,6 +25,11 @@
 ...
 LL |     }
    |     - `client` is later dropped here
+help: consider moving this into a `let` binding to create a shorter lived borrow
+  --> $DIR/issue-64130-4-async-move.rs:19:15
+   |
+LL |         match client.status() {
+   |               ^^^^^^^^^^^^^^^
    = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
new file mode 100644
index 0000000..3a814b4
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
@@ -0,0 +1,16 @@
+// edition:2018
+
+struct Foo(*const u8);
+
+unsafe impl Send for Foo {}
+
+async fn bar(_: Foo) {}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+    assert_send(async {
+    //~^ ERROR future cannot be sent between threads safely
+        bar(Foo(std::ptr::null())).await;
+    })
+}
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
new file mode 100644
index 0000000..7638ba1
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
@@ -0,0 +1,26 @@
+error: future cannot be sent between threads safely
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:12:5
+   |
+LL | fn assert_send<T: Send>(_: T) {}
+   |    -----------    ---- required by this bound in `assert_send`
+...
+LL |     assert_send(async {
+   |     ^^^^^^^^^^^ future returned by `main` is not `Send`
+   |
+   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*const u8`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
+   |
+LL |         bar(Foo(std::ptr::null())).await;
+   |         ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here
+   |         |       |
+   |         |       has type `*const u8`
+   |         await occurs here, with `std::ptr::null()` maybe used later
+help: consider moving this into a `let` binding to create a shorter lived borrow
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13
+   |
+LL |         bar(Foo(std::ptr::null())).await;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs b/src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs
new file mode 100644
index 0000000..dda4a15
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs
@@ -0,0 +1,33 @@
+// build-pass
+// edition:2018
+
+static mut A: [i32; 5] = [1, 2, 3, 4, 5];
+
+fn is_send_sync<T: Send + Sync>(_: T) {}
+
+async fn fun() {
+    let u = unsafe { A[async { 1 }.await] };
+    unsafe {
+        match A {
+            i if async { true }.await => (),
+            _ => (),
+        }
+    }
+}
+
+fn main() {
+    let index_block = async {
+        let u = unsafe { A[async { 1 }.await] };
+    };
+    let match_block = async {
+        unsafe {
+            match A {
+                i if async { true }.await => (),
+                _ => (),
+            }
+        }
+    };
+    is_send_sync(index_block);
+    is_send_sync(match_block);
+    is_send_sync(fun());
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
index 2c7a5cd..b12d7bc 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
@@ -8,6 +8,7 @@
 
 async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
     //~^ ERROR ambiguous lifetime bound
+    //~| ERROR ambiguous lifetime bound
     (a, b)
 }
 
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
index 59d7728..f9a1b4b 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
@@ -6,5 +6,13 @@
    |
    = help: add #![feature(member_constraints)] to the crate attributes to enable
 
-error: aborting due to previous error
+error: ambiguous lifetime bound in `impl Trait`
+  --> $DIR/ret-impl-trait-no-fg.rs:9:64
+   |
+LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+   |                                                                ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+   |
+   = help: add #![feature(member_constraints)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
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
index 9249308..f6e4c8b 100644
--- 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
@@ -4,7 +4,7 @@
 LL | async fn rec_1() {
    |                  ^ recursive `async fn`
    |
-   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
+   = 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
@@ -12,7 +12,7 @@
 LL | async fn rec_2() {
    |                  ^ recursive `async fn`
    |
-   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
 
 error: aborting due to 2 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 9ee0140..892d91e 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
@@ -4,7 +4,7 @@
 LL | async fn recursive_async_function() -> () {
    |                                        ^^ recursive `async fn`
    |
-   = note: a recursive `async fn` must be rewritten to return a boxed `dyn 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/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr
index 1efc200..2703cec 100644
--- a/src/test/ui/async-await/suggest-missing-await-closure.stderr
+++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await-closure.rs:16:18
    |
+LL | async fn make_u32() -> u32 {
+   |                        --- the `Output` of this `async fn`'s found opaque type
+...
 LL |         take_u32(x)
    |                  ^
    |                  |
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 7ab0244..6ac05a8 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:13:14
    |
+LL | async fn make_u32() -> u32 {
+   |                        --- the `Output` of this `async fn`'s found opaque type
+...
 LL |     take_u32(x)
    |              ^
    |              |
@@ -13,6 +16,9 @@
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:23:5
    |
+LL | async fn dummy() {}
+   |                  - the `Output` of this `async fn`'s found opaque type
+...
 LL |     dummy()
    |     ^^^^^^^ expected `()`, found opaque type
    |
diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs
index 79c043b..d313691 100644
--- a/src/test/ui/async-await/unresolved_type_param.rs
+++ b/src/test/ui/async-await/unresolved_type_param.rs
@@ -8,8 +8,16 @@
 async fn foo() {
     bar().await;
     //~^ ERROR type inside `async fn` body must be known in this context
+    //~| ERROR type inside `async fn` body must be known in this context
+    //~| ERROR type inside `async fn` body must be known in this context
+    //~| NOTE cannot infer type for type parameter `T`
+    //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE the type is part of the `async fn` body because of this `await`
+    //~| NOTE in this expansion of desugaring of `await`
+    //~| NOTE in this expansion of desugaring of `await`
     //~| NOTE in this expansion of desugaring of `await`
 }
 fn main() {}
diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr
index 3ffdb8c..6b9e960 100644
--- a/src/test/ui/async-await/unresolved_type_param.stderr
+++ b/src/test/ui/async-await/unresolved_type_param.stderr
@@ -10,6 +10,30 @@
 LL |     bar().await;
    |     ^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/unresolved_type_param.rs:9:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0698`.
diff --git a/src/test/ui/attr-shebang.rs b/src/test/ui/attr-shebang.rs
index cce31c9..3b0dc09 100644
--- a/src/test/ui/attr-shebang.rs
+++ b/src/test/ui/attr-shebang.rs
@@ -3,4 +3,3 @@
 #![allow(stable_features)]
 #![feature(rust1)]
 pub fn main() { }
-// ignore-license
diff --git a/src/test/ui/attributes/register-attr-tool-import.rs b/src/test/ui/attributes/register-attr-tool-import.rs
index 3d0cf91..e01dc4d 100644
--- a/src/test/ui/attributes/register-attr-tool-import.rs
+++ b/src/test/ui/attributes/register-attr-tool-import.rs
@@ -11,4 +11,5 @@
 
 #[renamed_attr] //~ ERROR cannot use an explicitly registered attribute through an import
 #[renamed_tool::attr] //~ ERROR cannot use a tool module through an import
+                      //~| ERROR cannot use a tool module through an import
 fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-import.stderr b/src/test/ui/attributes/register-attr-tool-import.stderr
index 6f280c8..59f5a86 100644
--- a/src/test/ui/attributes/register-attr-tool-import.stderr
+++ b/src/test/ui/attributes/register-attr-tool-import.stderr
@@ -22,5 +22,17 @@
 LL | use tool as renamed_tool; // OK
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: cannot use a tool module through an import
+  --> $DIR/register-attr-tool-import.rs:13:3
+   |
+LL | #[renamed_tool::attr]
+   |   ^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/register-attr-tool-import.rs:10:5
+   |
+LL | use tool as renamed_tool; // OK
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index 3e36f24..a0739a7 100644
--- a/src/test/ui/auto-ref-slice-plus-ref.stderr
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}>` in the current scope
+error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
@@ -8,7 +8,7 @@
    = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
+error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
    |
 LL |     a.test();
@@ -18,7 +18,7 @@
    = note: the following trait defines an item `test`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `[{integer}; 1]` in the current scope
+error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:10:11
    |
 LL |     ([1]).test();
@@ -28,7 +28,7 @@
    = note: the following trait defines an item `test`, perhaps you need to implement it:
            candidate #1: `MyIter`
 
-error[E0599]: no method named `test` found for type `&[{integer}; 1]` in the current scope
+error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:11:12
    |
 LL |     (&[1]).test();
diff --git a/src/test/ui/auxiliary/cdylib-dep.rs b/src/test/ui/auxiliary/cdylib-dep.rs
deleted file mode 100644
index 8bd2b33..0000000
--- a/src/test/ui/auxiliary/cdylib-dep.rs
+++ /dev/null
@@ -1 +0,0 @@
-#![crate_type = "dylib"]
diff --git a/src/test/ui/binding/empty-types-in-patterns.rs b/src/test/ui/binding/empty-types-in-patterns.rs
index 4271ffb..0d0dbca 100644
--- a/src/test/ui/binding/empty-types-in-patterns.rs
+++ b/src/test/ui/binding/empty-types-in-patterns.rs
@@ -1,7 +1,8 @@
 // run-pass
+
 #![feature(never_type, never_type_fallback)]
 #![feature(exhaustive_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(unreachable_patterns)]
 #![allow(unreachable_code)]
 #![allow(unused_variables)]
diff --git a/src/test/ui/binding/irrefutable-slice-patterns.rs b/src/test/ui/binding/irrefutable-slice-patterns.rs
index ac733ef..048e1e5 100644
--- a/src/test/ui/binding/irrefutable-slice-patterns.rs
+++ b/src/test/ui/binding/irrefutable-slice-patterns.rs
@@ -1,7 +1,6 @@
 // run-pass
-// #47096
 
-#![feature(slice_patterns)]
+// Regression test for #47096.
 
 fn foo(s: &[i32]) -> &[i32] {
     let &[ref xs @ ..] = s;
diff --git a/src/test/ui/binding/match-byte-array-patterns.rs b/src/test/ui/binding/match-byte-array-patterns.rs
index e877457..f0c988c 100644
--- a/src/test/ui/binding/match-byte-array-patterns.rs
+++ b/src/test/ui/binding/match-byte-array-patterns.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let buf = &[0u8; 4];
diff --git a/src/test/ui/binding/match-vec-alternatives.rs b/src/test/ui/binding/match-vec-alternatives.rs
index 9b06a86..af95eb9 100644
--- a/src/test/ui/binding/match-vec-alternatives.rs
+++ b/src/test/ui/binding/match-vec-alternatives.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
     match (l1, l2) {
diff --git a/src/test/ui/binding/zero_sized_subslice_match.rs b/src/test/ui/binding/zero_sized_subslice_match.rs
index 5326fa6..187c298 100644
--- a/src/test/ui/binding/zero_sized_subslice_match.rs
+++ b/src/test/ui/binding/zero_sized_subslice_match.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let x = [(), ()];
diff --git a/src/test/ui/block-result/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs
index 9b313d3..0b652a1 100644
--- a/src/test/ui/block-result/issue-3563.rs
+++ b/src/test/ui/block-result/issue-3563.rs
@@ -1,7 +1,7 @@
 trait A {
     fn a(&self) {
         || self.b()
-        //~^ ERROR no method named `b` found for type `&Self` in the current scope
+        //~^ ERROR no method named `b` found
     }
 }
 fn main() {}
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index 237b8c5..be551f6 100644
--- a/src/test/ui/block-result/issue-3563.stderr
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `b` found for type `&Self` in the current scope
+error[E0599]: no method named `b` found for reference `&Self` in the current scope
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr
index 890f680..cb3199e 100644
--- a/src/test/ui/bogus-tag.stderr
+++ b/src/test/ui/bogus-tag.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Hsl` found for type `Color` in the current scope
+error[E0599]: no variant or associated item named `Hsl` found for enum `Color` in the current scope
   --> $DIR/bogus-tag.rs:7:16
    |
 LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
index a70ccb7..0229ca3 100644
--- a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
@@ -1,6 +1,5 @@
 // Check that closure captures for slice patterns are inferred correctly
 
-#![feature(slice_patterns)]
 #![allow(unused_variables)]
 
 // run-pass
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
index 984eb88..32057d5 100644
--- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
@@ -1,7 +1,5 @@
 // Check that closure captures for slice patterns are inferred correctly
 
-#![feature(slice_patterns)]
-
 fn arr_by_ref(mut x: [String; 3]) {
     let f = || {
         let [ref y, ref z @ ..] = x;
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
index c5b27f5..483975e 100644
--- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:9:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:7:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -13,7 +13,7 @@
    |     - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:18:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:16:13
    |
 LL |     let mut f = || {
    |                 -- mutable borrow occurs here
@@ -27,7 +27,7 @@
    |     - mutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrowck-closures-slice-patterns.rs:27:5
+  --> $DIR/borrowck-closures-slice-patterns.rs:25:5
    |
 LL | fn arr_by_move(x: [String; 3]) {
    |                - move occurs because `x` has type `[std::string::String; 3]`, which does not implement the `Copy` trait
@@ -40,7 +40,7 @@
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:35:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:33:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -54,7 +54,7 @@
    |     - immutable borrow later used here
 
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/borrowck-closures-slice-patterns.rs:44:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:42:13
    |
 LL |     let mut f = || {
    |                 -- closure construction occurs here
@@ -68,7 +68,7 @@
    |     - first borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrowck-closures-slice-patterns.rs:53:5
+  --> $DIR/borrowck-closures-slice-patterns.rs:51:5
    |
 LL | fn arr_box_by_move(x: Box<[String; 3]>) {
    |                    - move occurs because `x` has type `std::boxed::Box<[std::string::String; 3]>`, which does not implement the `Copy` trait
@@ -81,7 +81,7 @@
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:61:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:59:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -95,7 +95,7 @@
    |     - immutable borrow later used here
 
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/borrowck-closures-slice-patterns.rs:70:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:68:13
    |
 LL |     let mut f = || {
    |                 -- closure construction occurs here
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs
index 8425960..c8bfbe0 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs
@@ -1,7 +1,5 @@
 // ignore-tidy-linelength
 
-#![feature(slice_patterns)]
-
 pub struct Foo {
   x: u32
 }
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
index 4213523..075e0e2 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:258:13
+  --> $DIR/borrowck-describe-lvalue.rs:256:13
    |
 LL |             let y = &mut x;
    |                     ------ first mutable borrow occurs here
@@ -9,7 +9,7 @@
    |             ------ first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:268:20
+  --> $DIR/borrowck-describe-lvalue.rs:266:20
    |
 LL |                    let y = &mut x;
    |                            ------ first mutable borrow occurs here
@@ -19,7 +19,7 @@
    |                    ------ first borrow later used here
 
 error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/borrowck-describe-lvalue.rs:266:16
+  --> $DIR/borrowck-describe-lvalue.rs:264:16
    |
 LL |              || {
    |               - inferred to be a `FnMut` closure
@@ -35,7 +35,7 @@
    = note: ...therefore, they cannot allow references to captured variables to escape
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:41:9
+  --> $DIR/borrowck-describe-lvalue.rs:39:9
    |
 LL |         let x = f.x();
    |                 - borrow of `f` occurs here
@@ -45,7 +45,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:48:9
+  --> $DIR/borrowck-describe-lvalue.rs:46:9
    |
 LL |         let x = g.x();
    |                 - borrow of `g` occurs here
@@ -55,7 +55,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:55:9
+  --> $DIR/borrowck-describe-lvalue.rs:53:9
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
@@ -65,7 +65,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:63:20
+  --> $DIR/borrowck-describe-lvalue.rs:61:20
    |
 LL |         let x = e.x();
    |                 - borrow of `e` occurs here
@@ -77,7 +77,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:71:9
+  --> $DIR/borrowck-describe-lvalue.rs:69:9
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
@@ -87,7 +87,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:78:9
+  --> $DIR/borrowck-describe-lvalue.rs:76:9
    |
 LL |         let x = f.x();
    |                 - borrow of `*f` occurs here
@@ -97,7 +97,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:85:9
+  --> $DIR/borrowck-describe-lvalue.rs:83:9
    |
 LL |         let x = g.x();
    |                 - borrow of `*g` occurs here
@@ -107,7 +107,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:92:9
+  --> $DIR/borrowck-describe-lvalue.rs:90:9
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
@@ -117,7 +117,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:100:20
+  --> $DIR/borrowck-describe-lvalue.rs:98:20
    |
 LL |         let x = e.x();
    |                 - borrow of `*e` occurs here
@@ -129,7 +129,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:109:9
+  --> $DIR/borrowck-describe-lvalue.rs:107:9
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
@@ -139,7 +139,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:117:15
+  --> $DIR/borrowck-describe-lvalue.rs:115:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -151,7 +151,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:122:18
+  --> $DIR/borrowck-describe-lvalue.rs:120:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -163,7 +163,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:127:25
+  --> $DIR/borrowck-describe-lvalue.rs:125:25
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -175,7 +175,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:132:28
+  --> $DIR/borrowck-describe-lvalue.rs:130:28
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -187,7 +187,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:143:15
+  --> $DIR/borrowck-describe-lvalue.rs:141:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -199,7 +199,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:148:18
+  --> $DIR/borrowck-describe-lvalue.rs:146:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -211,7 +211,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:153:15
+  --> $DIR/borrowck-describe-lvalue.rs:151:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -223,7 +223,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:158:18
+  --> $DIR/borrowck-describe-lvalue.rs:156:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -235,7 +235,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:171:13
+  --> $DIR/borrowck-describe-lvalue.rs:169:13
    |
 LL |         let x = &mut e;
    |                 ------ borrow of `e` occurs here
@@ -247,7 +247,7 @@
    |              - borrow later used here
 
 error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:171:18
+  --> $DIR/borrowck-describe-lvalue.rs:169:18
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
@@ -259,7 +259,7 @@
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:175:23
+  --> $DIR/borrowck-describe-lvalue.rs:173:23
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
@@ -271,7 +271,7 @@
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:188:22
+  --> $DIR/borrowck-describe-lvalue.rs:186:22
    |
 LL |         let x = &mut s;
    |                 ------ mutable borrow occurs here
@@ -283,7 +283,7 @@
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:194:28
+  --> $DIR/borrowck-describe-lvalue.rs:192:28
    |
 LL |         let x = &mut s;
    |                 ------ mutable borrow occurs here
@@ -295,7 +295,7 @@
    |              - mutable borrow later used here
 
 error[E0503]: cannot use `*v` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:236:9
+  --> $DIR/borrowck-describe-lvalue.rs:234:9
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -306,7 +306,7 @@
    |              - borrow later used here
 
 error[E0503]: cannot use `v[_].y` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:236:9
+  --> $DIR/borrowck-describe-lvalue.rs:234:9
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -317,7 +317,7 @@
    |              - borrow later used here
 
 error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:247:24
+  --> $DIR/borrowck-describe-lvalue.rs:245:24
    |
 LL |         let x = &mut v;
    |                 ------ mutable borrow occurs here
@@ -329,7 +329,7 @@
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:210:29
+  --> $DIR/borrowck-describe-lvalue.rs:208:29
    |
 LL |             let x = &mut block;
    |                     ---------- mutable borrow occurs here
@@ -340,7 +340,7 @@
    |                  - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:225:33
+  --> $DIR/borrowck-describe-lvalue.rs:223:33
    |
 LL |             let x = &mut block;
    |                     ---------- mutable borrow occurs here
@@ -351,7 +351,7 @@
    |                  - mutable borrow later used here
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/borrowck-describe-lvalue.rs:278:22
+  --> $DIR/borrowck-describe-lvalue.rs:276:22
    |
 LL |                 drop(x);
    |                      - value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
new file mode 100644
index 0000000..c1513fc
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
@@ -0,0 +1,116 @@
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        [.., _y] => {} //~ ERROR use of moved value
+    }
+}
+
+fn move_out_from_begin_field_and_end() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., _y] => {} //~ ERROR use of moved value
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., (_y, _)] => {} //~ ERROR use of moved value
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_subslice_and_const_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _, _] => {}
+    }
+    match a {
+        [(_x, _), _, _] => {} //~ ERROR use of moved value
+    }
+}
+
+fn move_out_by_subslice_and_const_index_end_field() {
+    let a = array();
+    match a {
+        [_, _, _y @ ..] => {}
+    }
+    match a {
+        [.., (_x, _)] => {} //~ ERROR use of moved value
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
new file mode 100644
index 0000000..84930b0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
@@ -0,0 +1,113 @@
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-match.rs:13:14
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+...
+LL |         [.., _y] => {}
+   |              ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-match.rs:23:14
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., _y] => {}
+   |              ^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-match.rs:33:15
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., (_y, _)] => {}
+   |               ^^ value used here after move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:44:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:55:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:66:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:77:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-match.rs:89:11
+   |
+LL |         [_y @ .., _, _] => {}
+   |          ------- value moved here
+...
+LL |         [(_x, _), _, _] => {}
+   |           ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-match.rs:99:15
+   |
+LL |         [_, _, _y @ ..] => {}
+   |                ------- value moved here
+...
+LL |         [.., (_x, _)] => {}
+   |               ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-match.rs:110:11
+   |
+LL |         [x @ .., _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
new file mode 100644
index 0000000..056b8e6
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
@@ -0,0 +1,115 @@
+// Due to #53114, which causes a "read" of the `_` patterns,
+// the borrow-checker refuses this code, while it should probably be allowed.
+// Once the bug is fixed, the test, which is derived from a
+// passing test for `let` statements, should become check-pass.
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_one_from_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., _y, _] => {}
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (_, _y)] => {}
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_index_field() {
+    let a = array();
+    match a {
+        [_, _y @ ..] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [(_x, _), _, _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_end_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (_x, _)] => {}
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, _y @ ..] => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
new file mode 100644
index 0000000..ff5eab2
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
@@ -0,0 +1,102 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11
+   |
+LL |         [_, _y @ ..] => {}
+   |             ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11
+   |
+LL |         [_y @ .., _] => {}
+   |          ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11
+   |
+LL |         [x @ .., _, _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
index 8f274cf..c91b428 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
new file mode 100644
index 0000000..604a25c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
@@ -0,0 +1,150 @@
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        [.., ref _y] => {} //~ ERROR [E0382]
+    }
+}
+
+fn move_out_from_begin_field_and_end() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., ref _y] => {} //~ ERROR [E0382]
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        [.., (ref _y, _)] => {} //~ ERROR [E0382]
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [ref _y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [_, _, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [ref _y @ .., _, _] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [_, _, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_subslice_and_const_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _, _] => {}
+    }
+    match a {
+        [(ref _x, _), _, _] => {} //~ ERROR [E0382]
+    }
+}
+
+fn move_out_by_subslice_and_const_index_end_field() {
+    let a = array();
+    match a {
+        [_, _, _y @ ..] => {}
+    }
+    match a {
+        [.., (ref _x, _)] => {} //~ ERROR [E0382]
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR [E0382]
+        [_, ref _y @ ..] => {}
+    }
+}
+
+// Move + Assign
+
+fn move_out_and_assign_end() {
+    let mut a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    a[2] = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_and_assign_end_field() {
+    let mut a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    a[2].1 = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_slice_and_assign_end() {
+    let mut a = array();
+    match a {
+        [_, _, _x @ ..] => {}
+    }
+    a[0] = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_slice_and_assign_end_field() {
+    let mut a = array();
+    match a {
+        [_, _, _x @ ..] => {}
+    }
+    a[0].1 = Default::default(); //~ ERROR [E0382]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
new file mode 100644
index 0000000..0ef6310
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
@@ -0,0 +1,157 @@
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:13:14
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+...
+LL |         [.., ref _y] => {}
+   |              ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., ref _y] => {}
+   |              ^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+...
+LL |         [.., (ref _y, _)] => {}
+   |               ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11
+   |
+LL |         [_y @ .., _, _] => {}
+   |          ------- value moved here
+...
+LL |         [(ref _x, _), _, _] => {}
+   |           ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15
+   |
+LL |         [_, _, _y @ ..] => {}
+   |                ------- value moved here
+...
+LL |         [.., (ref _x, _)] => {}
+   |               ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11
+   |
+LL |         [x @ .., _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+LL |     }
+LL |     a[2] = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+LL |     }
+LL |     a[2].1 = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5
+   |
+LL |         [_, _, _x @ ..] => {}
+   |                ------- value moved here
+LL |     }
+LL |     a[0] = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5
+   |
+LL |         [_, _, _x @ ..] => {}
+   |                ------- value moved here
+LL |     }
+LL |     a[0].1 = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
new file mode 100644
index 0000000..5afd683
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
@@ -0,0 +1,115 @@
+// Due to #53114, which causes a "read" of the `_` patterns,
+// the borrow-checker refuses this code, while it should probably be allowed.
+// Once the bug is fixed, the test, which is derived from a
+// passing test for `let` statements, should become check-pass.
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_one_from_end() {
+    let a = array();
+    match a {
+        [_, _, _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., ref _y, _] => {}
+    }
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    match a {
+        [_, _, (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (_, ref _y)] => {}
+    }
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    match a {
+        [_x, _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    match a {
+        [.., _x] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [ref _y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    match a {
+        [(_x, _), _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, ref _y @ ..] => {}
+    }
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    match a {
+        [.., (_x, _)] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [ref _y @ .., _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_index_field() {
+    let a = array();
+    match a {
+        [_, _y @ ..] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [(ref _x, _), _, _] => {}
+    }
+}
+
+fn move_out_by_const_subslice_and_end_index_field() {
+    let a = array();
+    match a {
+        [_y @ .., _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [.., (ref _x, _)] => {}
+    }
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    match a {
+        [x @ .., _, _] => {}
+    }
+    match a {
+        //~^ ERROR use of moved value
+        [_, ref _y @ ..] => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
new file mode 100644
index 0000000..a4042ce
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
@@ -0,0 +1,102 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11
+   |
+LL |         [_, _, _x] => {}
+   |                -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11
+   |
+LL |         [_, _, (_x, _)] => {}
+   |                 -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11
+   |
+LL |         [_x, _, _] => {}
+   |          -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11
+   |
+LL |         [.., _x] => {}
+   |              -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11
+   |
+LL |         [(_x, _), _, _] => {}
+   |           -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11
+   |
+LL |         [.., (_x, _)] => {}
+   |               -- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11
+   |
+LL |         [_, _y @ ..] => {}
+   |             ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11
+   |
+LL |         [_y @ .., _] => {}
+   |          ------- value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11
+   |
+LL |         [x @ .., _, _] => {}
+   |          ------ value moved here
+LL |     }
+LL |     match a {
+   |           ^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
index 57ce241..e3498ce 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
index 778beef..ad08367 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
index 2a7b891..7ad4116 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:12:14
+  --> $DIR/borrowck-move-out-from-array-use.rs:10:14
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -9,7 +9,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:18:14
+  --> $DIR/borrowck-move-out-from-array-use.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -19,7 +19,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-use.rs:24:15
+  --> $DIR/borrowck-move-out-from-array-use.rs:22:15
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -29,7 +29,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:32:10
+  --> $DIR/borrowck-move-out-from-array-use.rs:30:10
    |
 LL |     let [_x, _, _] = a;
    |          -- value moved here
@@ -39,7 +39,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:38:16
+  --> $DIR/borrowck-move-out-from-array-use.rs:36:16
    |
 LL |     let [.., _x] = a;
    |              -- value moved here
@@ -49,7 +49,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:44:10
+  --> $DIR/borrowck-move-out-from-array-use.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
    |           -- value moved here
@@ -59,7 +59,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:50:16
+  --> $DIR/borrowck-move-out-from-array-use.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
    |               -- value moved here
@@ -69,7 +69,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:56:11
+  --> $DIR/borrowck-move-out-from-array-use.rs:54:11
    |
 LL |     let [_y @ .., _, _] = a;
    |          ------- value moved here
@@ -79,7 +79,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:62:15
+  --> $DIR/borrowck-move-out-from-array-use.rs:60:15
    |
 LL |     let [_, _, _y @ ..] = a;
    |                ------- value moved here
@@ -89,7 +89,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:70:13
+  --> $DIR/borrowck-move-out-from-array-use.rs:68:13
    |
 LL |     let [x @ .., _] = a;
    |          ------ value moved here
@@ -99,7 +99,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:78:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:76:5
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -109,7 +109,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:84:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:82:5
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -119,7 +119,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:90:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:88:5
    |
 LL |     let [_, _, _x @ ..] = a;
    |                ------- value moved here
@@ -129,7 +129,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:96:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:94:5
    |
 LL |     let [_, _, _x @ ..] = a;
    |                ------- value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.rs b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
index f9d3f6f..8375581 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
index 08134a2..b7babd9 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:12:14
+  --> $DIR/borrowck-move-out-from-array.rs:10:14
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -9,7 +9,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:18:14
+  --> $DIR/borrowck-move-out-from-array.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -19,7 +19,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:24:15
+  --> $DIR/borrowck-move-out-from-array.rs:22:15
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -29,7 +29,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:32:10
+  --> $DIR/borrowck-move-out-from-array.rs:30:10
    |
 LL |     let [_x, _, _] = a;
    |          -- value moved here
@@ -39,7 +39,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:38:16
+  --> $DIR/borrowck-move-out-from-array.rs:36:16
    |
 LL |     let [.., _x] = a;
    |              -- value moved here
@@ -49,7 +49,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:44:10
+  --> $DIR/borrowck-move-out-from-array.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
    |           -- value moved here
@@ -59,7 +59,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:50:16
+  --> $DIR/borrowck-move-out-from-array.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
    |               -- value moved here
@@ -69,7 +69,7 @@
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:56:11
+  --> $DIR/borrowck-move-out-from-array.rs:54:11
    |
 LL |     let [_y @ .., _, _] = a;
    |          ------- value moved here
@@ -79,7 +79,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:62:15
+  --> $DIR/borrowck-move-out-from-array.rs:60:15
    |
 LL |     let [_, _, _y @ ..] = a;
    |                ------- value moved here
@@ -89,7 +89,7 @@
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:70:13
+  --> $DIR/borrowck-move-out-from-array.rs:68:13
    |
 LL |     let [x @ .., _] = a;
    |          ------ value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
index fa9a3c2..8ece81a 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
@@ -1,7 +1,5 @@
 // Test that we do not permit moves from &[] matched by a vec pattern.
 
-#![feature(slice_patterns)]
-
 #[derive(Clone, Debug)]
 struct Foo {
     string: String
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
index 8fb4c06..a345c12 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
-  --> $DIR/borrowck-move-out-of-vec-tail.rs:19:19
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:17:19
    |
 LL |             match tail {
    |                   ^^^^ cannot move out of here
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
index 7d91a21..a8e56f6 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
index f03a2ab..6b210d7 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
index e50e7eb..0432aaf 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:8:13
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:6:13
    |
 LL |     let [ref first, ref second, ..] = *s;
    |                     ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@
    |                  ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:14:14
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:12:14
    |
 LL |     let [.., ref fourth, ref third, _, ref first] = *s;
    |                          --------- immutable borrow occurs here
@@ -19,7 +19,7 @@
    |                  ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:16
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:19:16
    |
 LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
    |                 ------------- immutable borrow occurs here
@@ -30,7 +30,7 @@
    |                                              --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:23:19
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:19
    |
 LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
    |                                ------------- immutable borrow occurs here
@@ -41,7 +41,7 @@
    |                                   --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:28:14
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:26:14
    |
 LL |     let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s;
    |                                               --------------- immutable borrow occurs here
@@ -52,7 +52,7 @@
    |                                     ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:34:13
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:32:13
    |
 LL |     let [ref first, ref second, ..] = *s;
    |                     ---------- immutable borrow occurs here
@@ -62,7 +62,7 @@
    |                  ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:41:10
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:39:10
    |
 LL |     let [.., ref second, ref first] = *s;
    |              ---------- immutable borrow occurs here
@@ -72,7 +72,7 @@
    |                  ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:48:10
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:46:10
    |
 LL |     let [_,  ref s1 @ ..] = *s;
    |              ----------- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
index 048813b..4367596 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
@@ -1,7 +1,4 @@
 // run-pass
-//compile-flags: -Z borrowck=mir
-
-#![feature(slice_patterns)]
 
 fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
     match *v {
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
index e69071f..6390dc3 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
index 2ef9874..0e1c90a 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
index b6f5ac6..d3388e0 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:8:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:6:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:16:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:14:21
    |
 LL |     if let [.., ref fourth, ref third, _, ref first] = *s {
    |                             --------- immutable borrow occurs here
@@ -19,7 +19,7 @@
    |                          ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:24:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:22:20
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                    ------------- immutable borrow occurs here
@@ -29,7 +29,7 @@
    |                                                      --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:27:23
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:25:23
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -40,7 +40,7 @@
    |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:30:26
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:28:26
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -51,7 +51,7 @@
    |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:35:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:33:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -61,7 +61,7 @@
    |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:38:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:36:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -72,7 +72,7 @@
    |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:41:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:39:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                              --------------- immutable borrow occurs here
@@ -83,7 +83,7 @@
    |                                ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:49:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:47:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -93,7 +93,7 @@
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:58:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:56:17
    |
 LL |     if let [.., ref second, ref first] = *s {
    |                 ---------- immutable borrow occurs here
@@ -103,7 +103,7 @@
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:67:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:65:17
    |
 LL |     if let [_, _, _, ref s1 @ ..] = *s {
    |                      ----------- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
index 53a9bce..cd853b8 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a<'a>() -> &'a [isize] {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
index da6d929..170982b 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:10:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:8:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
@@ -8,7 +8,7 @@
    |     ^^^^ returns a value referencing data owned by the current function
 
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:20:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:18:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
@@ -17,7 +17,7 @@
    |     ^^^^ returns a value referencing data owned by the current function
 
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:30:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:28:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
index dd9023f..05859c9 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a() {
     let mut v = vec![1, 2, 3];
     let vb: &mut [isize] = &mut v;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
index 251f445..5141fcc 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `v` as mutable more than once at a time
-  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:8:13
+  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:6:13
    |
 LL |     let vb: &mut [isize] = &mut v;
    |                            ------ first mutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
index 4202230..9b8ba2e 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
@@ -1,7 +1,3 @@
-// http://rust-lang.org/COPYRIGHT.
-
-#![feature(slice_patterns)]
-
 fn main() {
     let mut a = [1, 2, 3, 4];
     let t = match a {
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
index 9f8e6fe..ff70ba9f 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `a[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:8:5
    |
 LL |         [1, 2, ref tail @ ..] => tail,
    |                ------------- borrow of `a[_]` occurs here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
index e274d10..67b6c12 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -1,6 +1,5 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(slice_patterns)]
 
 fn a() {
     let mut vec = [box 1, box 2, box 3];
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index a3324f2..e2c0852 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:10:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:9:13
    |
 LL |         [box ref _a, _, _] => {
    |              ------ borrow of `vec[_]` occurs here
@@ -11,7 +11,7 @@
    |             -- borrow later used here
 
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
    |
 LL |         &mut [ref _b @ ..] => {
    |               ----------- borrow of `vec[_]` occurs here
@@ -23,7 +23,7 @@
    |             -- borrow later used here
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:35:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:34:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -45,7 +45,7 @@
    |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:47:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:46:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -55,7 +55,7 @@
    |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:56:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -74,7 +74,7 @@
    |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:66:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:65:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -84,7 +84,7 @@
    |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:75:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -100,7 +100,7 @@
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:86:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
index c35be2f..3987282 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a<'a>() -> &'a isize {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
index c1290a6..7e21c55 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:10:5
+  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:8:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
index da918ba..141ad5b 100644
--- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
@@ -26,6 +26,7 @@
 
     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
         //~^ ERROR method not compatible with trait
+        //~| ERROR method not compatible with trait
         //
         // Note: This is a terrible error message. It is caused
         // because, in the trait, 'b is early bound, and in the impl,
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index 4f86ffb..ad39b36 100644
--- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -35,8 +35,27 @@
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |                        ^^
 
+error[E0308]: method not compatible with trait
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
+              found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
+note: the lifetime `'c` as defined on the method body at 27:24...
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |                        ^^
+note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
+   |
+LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |                        ^^
+
 error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:20
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20
    |
 LL |     fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
    |                    ---------------- lifetimes in impl do not match this method in trait
@@ -45,7 +64,7 @@
    |                    ^ lifetimes do not match method in trait
 
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:48:5
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:49:5
    |
 LL |     fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
    |     ------------------------------------------------------- definition of `another_bound` from trait
@@ -53,7 +72,7 @@
 LL |     fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0195, E0276, E0308.
 For more information about an error, try `rustc --explain E0195`.
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 8b70b15..89107e7 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
@@ -87,12 +87,12 @@
   --> $DIR/variadic-ffi-4.rs:24:11
    |
 LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                                    - let's call the lifetime of this reference `'1`
+   |                                                    - let's call the lifetime of this reference `'3`
 LL |     ap0 = &mut ap1;
    |     ------^^^^^^^^
    |     |     |
    |     |     borrowed value does not live long enough
-   |     assignment requires that `ap1` is borrowed for `'1`
+   |     assignment requires that `ap1` is borrowed for `'3`
 ...
 LL | }
    | - `ap1` dropped here while still borrowed
diff --git a/src/test/ui/cdylib-deps-must-be-static.rs b/src/test/ui/cdylib-deps-must-be-static.rs
deleted file mode 100644
index abf954d..0000000
--- a/src/test/ui/cdylib-deps-must-be-static.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// build-fail
-// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
-// aux-build:cdylib-dep.rs
-// ignore-musl
-// ignore-cloudabi
-// ignore-emscripten
-// ignore-sgx no dynamic libraries
-#![crate_type = "cdylib"]
-
-extern crate cdylib_dep;
diff --git a/src/test/ui/cdylib-deps-must-be-static.stderr b/src/test/ui/cdylib-deps-must-be-static.stderr
deleted file mode 100644
index a1dc8e9..0000000
--- a/src/test/ui/cdylib-deps-must-be-static.stderr
+++ /dev/null
@@ -1,4 +0,0 @@
-error: crate `cdylib_dep` required to be available in rlib format, but was not found in this form
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/class-cast-to-trait.stderr b/src/test/ui/class-cast-to-trait.stderr
index 4cab52e..0f932cd 100644
--- a/src/test/ui/class-cast-to-trait.stderr
+++ b/src/test/ui/class-cast-to-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `eat` found for type `std::boxed::Box<dyn Noisy>` in the current scope
+error[E0599]: no method named `eat` found for struct `std::boxed::Box<dyn Noisy>` in the current scope
   --> $DIR/class-cast-to-trait.rs:53:8
    |
 LL |   nyan.eat();
diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr
index 63236cf..3c4ae45 100644
--- a/src/test/ui/closures/closure-reform-bad.stderr
+++ b/src/test/ui/closures/closure-reform-bad.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/closure-reform-bad.rs:11:15
    |
+LL |     let f = |s: &str| println!("{}{}", s, string);
+   |             ------------------------------------- the found closure
 LL |     call_bare(f)
    |               ^ expected fn pointer, found closure
    |
diff --git a/src/test/ui/closures/issue-68025.rs b/src/test/ui/closures/issue-68025.rs
new file mode 100644
index 0000000..261bfd6
--- /dev/null
+++ b/src/test/ui/closures/issue-68025.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+fn foo<F, G>(_: G, _: Box<F>)
+where
+    F: Fn(),
+    G: Fn(Box<F>),
+{
+}
+
+fn main() {
+    foo(|f| (*f)(), Box::new(|| {}));
+}
diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
index 303d83d..44e5c6a 100644
--- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
+++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
@@ -29,7 +29,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:13:13
    |
 LL |     let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>;
-   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>`
@@ -38,7 +38,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:14:13
    |
 LL |     let _ = box if true { false } else { true }: Box<dyn Debug>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
    |
    = note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
               found struct `std::boxed::Box<bool>`
@@ -47,7 +47,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:15:13
    |
 LL |     let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
    |
    = note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
               found struct `std::boxed::Box<char>`
@@ -83,7 +83,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:21:13
    |
 LL |     let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _;
-   |             ^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected reference `&dyn std::ops::Fn(i32) -> u8`
               found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]`
@@ -92,7 +92,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:22:13
    |
 LL |     let _ = &if true { false } else { true }: &dyn Debug;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
    |
    = note: expected reference `&dyn std::fmt::Debug`
               found reference `&bool`
@@ -101,7 +101,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:23:13
    |
 LL |     let _ = &match true { true => 'a', false => 'b' }: &dyn Debug;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
    |
    = note: expected reference `&dyn std::fmt::Debug`
               found reference `&char`
@@ -119,7 +119,7 @@
   --> $DIR/coerce-expect-unsized-ascribed.rs:26:13
    |
 LL |     let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`
diff --git a/src/test/ui/coherence/coherence_inherent.stderr b/src/test/ui/coherence/coherence_inherent.stderr
index e719d52..3d37d8a 100644
--- a/src/test/ui/coherence/coherence_inherent.stderr
+++ b/src/test/ui/coherence/coherence_inherent.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `the_fn` found for type `&Lib::TheStruct` in the current scope
+error[E0599]: no method named `the_fn` found for reference `&Lib::TheStruct` in the current scope
   --> $DIR/coherence_inherent.rs:31:11
    |
 LL |         s.the_fn();
diff --git a/src/test/ui/coherence/coherence_inherent_cc.stderr b/src/test/ui/coherence/coherence_inherent_cc.stderr
index c666c1a..d968c8b 100644
--- a/src/test/ui/coherence/coherence_inherent_cc.stderr
+++ b/src/test/ui/coherence/coherence_inherent_cc.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `the_fn` found for type `&coherence_inherent_cc_lib::TheStruct` in the current scope
+error[E0599]: no method named `the_fn` found for reference `&coherence_inherent_cc_lib::TheStruct` in the current scope
   --> $DIR/coherence_inherent_cc.rs:23:11
    |
 LL |         s.the_fn();
diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs
index cc986b2..8e9c116 100644
--- a/src/test/ui/conflicting-repr-hints.rs
+++ b/src/test/ui/conflicting-repr-hints.rs
@@ -1,16 +1,24 @@
 #![allow(dead_code)]
 
 #[repr(C)]
-enum A { A }
+enum A {
+    A,
+}
 
 #[repr(u64)]
-enum B { B }
+enum B {
+    B,
+}
 
-#[repr(C, u64)] //~ WARNING conflicting representation hints
-enum C { C }
+#[repr(C, u64)] //~ ERROR conflicting representation hints
+enum C {
+    C,
+}
 
-#[repr(u32, u64)] //~ WARNING conflicting representation hints
-enum D { D }
+#[repr(u32, u64)] //~ ERROR conflicting representation hints
+enum D {
+    D,
+}
 
 #[repr(C, packed)]
 struct E(i32);
@@ -37,20 +45,23 @@
 struct K(i32);
 
 #[repr(packed, align(8))]
-union X { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union X {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 #[repr(packed)]
 #[repr(align(8))]
-union Y { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union Y {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 #[repr(align(8))]
 #[repr(packed)]
-union Z { //~ ERROR type has conflicting packed and align representation hints
-    i: i32
+union Z {
+    //~^ ERROR type has conflicting packed and align representation hints
+    i: i32,
 }
 
 fn main() {}
diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr
index 414c15f..0dfe360 100644
--- a/src/test/ui/conflicting-repr-hints.stderr
+++ b/src/test/ui/conflicting-repr-hints.stderr
@@ -1,70 +1,73 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/conflicting-repr-hints.rs:9:8
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:13:8
    |
 LL | #[repr(C, u64)]
    |        ^  ^^^
 
-warning[E0566]: conflicting representation hints
-  --> $DIR/conflicting-repr-hints.rs:12:8
+error[E0566]: conflicting representation hints
+  --> $DIR/conflicting-repr-hints.rs:18:8
    |
 LL | #[repr(u32, u64)]
    |        ^^^  ^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:19:1
+  --> $DIR/conflicting-repr-hints.rs:27:1
    |
 LL | struct F(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:23:1
+  --> $DIR/conflicting-repr-hints.rs:31:1
    |
 LL | struct G(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:27:1
+  --> $DIR/conflicting-repr-hints.rs:35:1
    |
 LL | struct H(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0634]: type has conflicting packed representation hints
-  --> $DIR/conflicting-repr-hints.rs:30:1
+  --> $DIR/conflicting-repr-hints.rs:38:1
    |
 LL | struct I(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0634]: type has conflicting packed representation hints
-  --> $DIR/conflicting-repr-hints.rs:34:1
+  --> $DIR/conflicting-repr-hints.rs:42:1
    |
 LL | struct J(i32);
    | ^^^^^^^^^^^^^^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:40:1
+  --> $DIR/conflicting-repr-hints.rs:48:1
    |
 LL | / union X {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:46:1
+  --> $DIR/conflicting-repr-hints.rs:55:1
    |
 LL | / union Y {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
 error[E0587]: type has conflicting packed and align representation hints
-  --> $DIR/conflicting-repr-hints.rs:52:1
+  --> $DIR/conflicting-repr-hints.rs:62:1
    |
 LL | / union Z {
-LL | |     i: i32
+LL | |
+LL | |     i: i32,
 LL | | }
    | |_^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0566, E0587.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr
index 79ba931..d6b399a 100644
--- a/src/test/ui/confuse-field-and-method/issue-18343.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-18343.rs:6:28: 6:33]>` in the current scope
   --> $DIR/issue-18343.rs:7:7
    |
 LL | struct Obj<F> where F: FnMut() -> u32 {
diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
index a44b971..f9dfddd 100644
--- a/src/test/ui/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
   --> $DIR/issue-2392.rs:36:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -12,7 +12,7 @@
 LL |     (o_closure.closure)();
    |     ^                 ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
   --> $DIR/issue-2392.rs:38:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -23,7 +23,7 @@
    |               |
    |               field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:42:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -37,7 +37,7 @@
 LL |     (o_func.closure)();
    |     ^              ^
 
-error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope
   --> $DIR/issue-2392.rs:45:14
    |
 LL | struct BoxedObj {
@@ -51,7 +51,7 @@
 LL |     (boxed_fn.boxed_closure)();
    |     ^                      ^
 
-error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope
   --> $DIR/issue-2392.rs:48:19
    |
 LL | struct BoxedObj {
@@ -65,7 +65,7 @@
 LL |     (boxed_closure.boxed_closure)();
    |     ^                           ^
 
-error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:53:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -79,7 +79,7 @@
 LL |     (w.wrap.closure)();
    |     ^              ^
 
-error[E0599]: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<fn() -> u32 {func}>` in the current scope
   --> $DIR/issue-2392.rs:55:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -90,7 +90,7 @@
    |            |
    |            field, not a method
 
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
   --> $DIR/issue-2392.rs:58:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -104,7 +104,7 @@
 LL |     (check_expression().closure)();
    |     ^                          ^
 
-error[E0599]: no method named `f1` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f1` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:64:31
    |
 LL | struct FuncContainer {
@@ -118,7 +118,7 @@
 LL |             ((*self.container).f1)(1);
    |             ^                    ^
 
-error[E0599]: no method named `f2` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f2` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:65:31
    |
 LL | struct FuncContainer {
@@ -132,7 +132,7 @@
 LL |             ((*self.container).f2)(1);
    |             ^                    ^
 
-error[E0599]: no method named `f3` found for type `FuncContainer` in the current scope
+error[E0599]: no method named `f3` found for struct `FuncContainer` in the current scope
   --> $DIR/issue-2392.rs:66:31
    |
 LL | struct FuncContainer {
diff --git a/src/test/ui/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr
index b2f7894..a8d97bd 100644
--- a/src/test/ui/confuse-field-and-method/issue-32128.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `example` found for type `Example` in the current scope
+error[E0599]: no method named `example` found for struct `Example` in the current scope
   --> $DIR/issue-32128.rs:12:10
    |
 LL | struct Example {
diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr
index af29a99..c109896 100644
--- a/src/test/ui/confuse-field-and-method/issue-33784.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for type `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
   --> $DIR/issue-33784.rs:27:7
    |
 LL |     p.closure();
@@ -9,7 +9,7 @@
 LL |     (p.closure)();
    |     ^         ^
 
-error[E0599]: no method named `fn_ptr` found for type `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope
   --> $DIR/issue-33784.rs:29:7
    |
 LL |     q.fn_ptr();
@@ -20,7 +20,7 @@
 LL |     (q.fn_ptr)();
    |     ^        ^
 
-error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scope
+error[E0599]: no method named `c_fn_ptr` found for reference `&D` in the current scope
   --> $DIR/issue-33784.rs:32:7
    |
 LL |     s.c_fn_ptr();
diff --git a/src/test/ui/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr
index 97c949e..82cb235 100644
--- a/src/test/ui/confuse-field-and-method/private-field.stderr
+++ b/src/test/ui/confuse-field-and-method/private-field.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `dog_age` found for type `animal::Dog` in the current scope
+error[E0599]: no method named `dog_age` found for struct `animal::Dog` in the current scope
   --> $DIR/private-field.rs:16:23
    |
 LL |     pub struct Dog {
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
index 5c37468..6e5afcd 100644
--- a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
+++ b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
@@ -3,6 +3,9 @@
    |
 LL | pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     Vec::<A>::new()
+   |     --------------- this returned value is of type `std::vec::Vec<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::vec::Vec<A>`
    = note: the return type of a function must have a statically known size
@@ -12,6 +15,9 @@
    |
 LL | pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     Vec::<A>::new()
+   |     --------------- this returned value is of type `std::vec::Vec<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::vec::Vec<A>`
    = note: the return type of a function must have a statically known size
@@ -21,6 +27,9 @@
    |
 LL | pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
    |                                                ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
@@ -30,6 +39,9 @@
    |
 LL | pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
@@ -39,6 +51,9 @@
    |
 LL | pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a mut [B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
index bfdff8e..4869f48 100644
--- a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
+++ b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
@@ -11,6 +11,9 @@
    |
 LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -28,6 +31,9 @@
    |
 LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -45,6 +51,9 @@
    |
 LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
    |                                    ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -62,6 +71,9 @@
    |
 LL | pub fn no_fused_iterator() -> impl FusedIterator {
    |                               ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -79,6 +91,9 @@
    |
 LL | pub fn no_trusted_len() -> impl TrustedLen {
    |                            ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -96,6 +111,9 @@
    |
 LL | pub fn no_clone() -> impl Clone {
    |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -113,6 +131,9 @@
    |
 LL | pub fn no_debug() -> impl Debug {
    |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
index f3be7b5..d996bf5 100644
--- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
+++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
@@ -1,10 +1,9 @@
-// run-pass
-
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
 #[allow(dead_code)]
-struct ArithArrayLen<const N: usize>([u32; 0 + N]); // ok
+struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+//~^ ERROR constant expression depends on a generic parameter
 
 #[derive(PartialEq, Eq)]
 struct Config {
@@ -12,7 +11,7 @@
 }
 
 struct B<const CFG: Config> {
-    arr: [u8; CFG.arr_size], // ok
+    arr: [u8; CFG.arr_size], //~ ERROR constant expression depends on a generic parameter
 }
 
 const C: Config = Config { arr_size: 5 };
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
index 274f976..6ae70c4 100644
--- a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
+++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
@@ -1,8 +1,26 @@
 warning: the feature `const_generics` is incomplete and may cause the compiler to crash
-  --> $DIR/array-size-in-generic-struct-param.rs:3:12
+  --> $DIR/array-size-in-generic-struct-param.rs:1:12
    |
 LL | #![feature(const_generics)]
    |            ^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
 
+error: constant expression depends on a generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:5:38
+   |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+   |                                      ^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:14:5
+   |
+LL |     arr: [u8; CFG.arr_size],
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/const-generic-type_name.rs b/src/test/ui/const-generics/const-generic-type_name.rs
new file mode 100644
index 0000000..2858642
--- /dev/null
+++ b/src/test/ui/const-generics/const-generic-type_name.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+#[derive(Debug)]
+struct S<const N: usize>;
+
+fn main() {
+    assert_eq!(std::any::type_name::<S<3>>(), "const_generic_type_name::S<3usize>");
+}
diff --git a/src/test/ui/const-generics/const-generic-type_name.stderr b/src/test/ui/const-generics/const-generic-type_name.stderr
new file mode 100644
index 0000000..6b60a77
--- /dev/null
+++ b/src/test/ui/const-generics/const-generic-type_name.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-generic-type_name.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.rs b/src/test/ui/const-generics/const-param-elided-lifetime.rs
new file mode 100644
index 0000000..5679dd3
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-elided-lifetime.rs
@@ -0,0 +1,24 @@
+// Elided lifetimes within the type of a const generic parameters is disallowed. This matches the
+// behaviour of trait bounds where `fn foo<T: Ord<&u8>>() {}` is illegal. Though we could change
+// elided lifetimes within the type of a const generic parameters to be 'static, like elided
+// lifetimes within const/static items.
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct A<const N: &u8>;
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+trait B {}
+
+impl<const N: &u8> A<N> { //~ ERROR `&` without an explicit lifetime name cannot be used here
+    fn foo<const M: &u8>(&self) {}
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+}
+
+impl<const N: &u8> B for A<N> {}
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+
+fn bar<const N: &u8>() {}
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.stderr
new file mode 100644
index 0000000..93133c5
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-elided-lifetime.stderr
@@ -0,0 +1,40 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:9:19
+   |
+LL | struct A<const N: &u8>;
+   |                   ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:13:15
+   |
+LL | impl<const N: &u8> A<N> {
+   |               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:14:21
+   |
+LL |     fn foo<const M: &u8>(&self) {}
+   |                     ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:18:15
+   |
+LL | impl<const N: &u8> B for A<N> {}
+   |               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:21:17
+   |
+LL | fn bar<const N: &u8>() {}
+   |                 ^ explicit lifetime name needed here
+
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-elided-lifetime.rs:6:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs
new file mode 100644
index 0000000..30fbfda
--- /dev/null
+++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) {
+    f([1, 2, 3]);
+}
+
+fn takes_closure_of_array_3_apit(f: impl Fn([i32; 3])) {
+    f([1, 2, 3]);
+}
+
+fn returns_closure_of_array_3() -> impl Fn([i32; 3]) {
+    |_| {}
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr
new file mode 100644
index 0000000..7f37f3e
--- /dev/null
+++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
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 47b090c..19e7d20 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
@@ -4,7 +4,7 @@
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
    |                                  ^^ unexpected const argument
 
-error[E0599]: no method named `f` found for type `S` in the current scope
+error[E0599]: no method named `f` found for struct `S` in the current scope
   --> $DIR/invalid-const-arg-for-type-param.rs:7:7
    |
 LL | struct S;
diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs
index 1de6baf..af63d1f 100644
--- a/src/test/ui/consts/array-literal-index-oob.rs
+++ b/src/test/ui/consts/array-literal-index-oob.rs
@@ -1,7 +1,11 @@
-// build-fail
+// build-pass
+// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
+
+#![warn(const_err)]
 
 fn main() {
-    &{[1, 2, 3][4]};
-    //~^ ERROR index out of bounds
-    //~| ERROR reaching this expression at runtime will panic or abort
+    &{ [1, 2, 3][4] };
+    //~^ WARN index out of bounds
+    //~| WARN reaching this expression at runtime will panic or abort
+    //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index f3ef166..e93aa32 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -1,18 +1,26 @@
-error: index out of bounds: the len is 3 but the index is 4
-  --> $DIR/array-literal-index-oob.rs:4:7
+warning: index out of bounds: the len is 3 but the index is 4
+  --> $DIR/array-literal-index-oob.rs:7:8
    |
-LL |     &{[1, 2, 3][4]};
-   |       ^^^^^^^^^^^^
+LL |     &{ [1, 2, 3][4] };
+   |        ^^^^^^^^^^^^
    |
-   = note: `#[deny(const_err)]` on by default
+note: lint level defined here
+  --> $DIR/array-literal-index-oob.rs:4:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/array-literal-index-oob.rs:4:7
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/array-literal-index-oob.rs:7:8
    |
-LL |     &{[1, 2, 3][4]};
-   |     --^^^^^^^^^^^^-
-   |       |
-   |       indexing out of bounds: the len is 3 but the index is 4
+LL |     &{ [1, 2, 3][4] };
+   |     ---^^^^^^^^^^^^--
+   |        |
+   |        indexing out of bounds: the len is 3 but the index is 4
 
-error: aborting due to 2 previous errors
+warning: erroneous constant used
+  --> $DIR/array-literal-index-oob.rs:7:5
+   |
+LL |     &{ [1, 2, 3][4] };
+   |     ^^^^^^^^^^^^^^^^^ referenced constant has errors
 
diff --git a/src/test/ui/consts/associated_const_generic.rs b/src/test/ui/consts/associated_const_generic.rs
new file mode 100644
index 0000000..dee376c
--- /dev/null
+++ b/src/test/ui/consts/associated_const_generic.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+trait TraitA {
+    const VALUE: usize;
+}
+
+struct A;
+impl TraitA for A {
+    const VALUE: usize = 1;
+}
+
+trait TraitB {
+    type MyA: TraitA;
+    const VALUE: usize = Self::MyA::VALUE;
+}
+
+struct B;
+impl TraitB for B {
+    type MyA = A;
+}
+
+fn main() {
+    let _ = [0; A::VALUE];
+    let _ = [0; B::VALUE]; // Indirectly refers to `A::VALUE`
+}
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs
index 96f67c9..2058d2e 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs
@@ -10,4 +10,5 @@
 fn main() {
     println!("{}", FOO);
     //~^ ERROR
+    //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
index ec18f8f..b5f5f84 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -18,6 +18,12 @@
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:11:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
index 9369702..9300d95 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
@@ -14,6 +14,7 @@
     match -128i8 {
         NEG_NEG_128 => println!("A"),
         //~^ ERROR could not evaluate constant pattern
+        //~| ERROR could not evaluate constant pattern
         _ => println!("B"),
     }
 }
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
index 13f00c4..26728cf 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -4,5 +4,11 @@
 LL |         NEG_NEG_128 => println!("A"),
    |         ^^^^^^^^^^^
 
-error: aborting due to previous error
+error: could not evaluate constant pattern
+  --> $DIR/const-eval-overflow-2.rs:15:9
+   |
+LL |         NEG_NEG_128 => println!("A"),
+   |         ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
index a5f04d0..81f5382 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
@@ -4,7 +4,9 @@
 #![feature(const_fn)]
 #![allow(const_err)]
 
-fn double(x: usize) -> usize { x * 2 }
+fn double(x: usize) -> usize {
+    x * 2
+}
 const X: fn(usize) -> usize = double;
 
 const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
index 19f37fa..f99505c 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
@@ -1,11 +1,11 @@
 warning: skipping const checks
-  --> $DIR/const_fn_ptr_fail2.rs:11:5
+  --> $DIR/const_fn_ptr_fail2.rs:13:5
    |
 LL |     x(y)
    |     ^^^^
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/const_fn_ptr_fail2.rs:18:5
+  --> $DIR/const_fn_ptr_fail2.rs:20:5
    |
 LL |     assert_eq!(Y, 4);
    |     ^^^^^^^^^^^-^^^^^
@@ -15,7 +15,7 @@
    = 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[E0080]: evaluation of constant expression failed
-  --> $DIR/const_fn_ptr_fail2.rs:20:5
+  --> $DIR/const_fn_ptr_fail2.rs:22:5
    |
 LL |     assert_eq!(Z, 4);
    |     ^^^^^^^^^^^-^^^^^
diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs
index 849c81a..9109307 100644
--- a/src/test/ui/consts/const-eval/issue-43197.rs
+++ b/src/test/ui/consts/const-eval/issue-43197.rs
@@ -7,11 +7,13 @@
 }
 
 fn main() {
-    const X: u32 = 0-1;
+    const X: u32 = 0 - 1;
     //~^ WARN any use of this value will cause
-    const Y: u32 = foo(0-1);
+    const Y: u32 = foo(0 - 1);
     //~^ WARN any use of this value will cause
     println!("{} {}", X, Y);
     //~^ ERROR evaluation of constant expression failed
     //~| ERROR evaluation of constant expression failed
+    //~| WARN erroneous constant used [const_err]
+    //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
index a1b3a05..23b54d9 100644
--- a/src/test/ui/consts/const-eval/issue-43197.stderr
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -1,8 +1,8 @@
 warning: any use of this value will cause an error
   --> $DIR/issue-43197.rs:10:20
    |
-LL |     const X: u32 = 0-1;
-   |     ---------------^^^-
+LL |     const X: u32 = 0 - 1;
+   |     ---------------^^^^^-
    |                    |
    |                    attempt to subtract with overflow
    |
@@ -15,8 +15,8 @@
 warning: any use of this value will cause an error
   --> $DIR/issue-43197.rs:12:24
    |
-LL |     const Y: u32 = foo(0-1);
-   |     -------------------^^^--
+LL |     const Y: u32 = foo(0 - 1);
+   |     -------------------^^^^^--
    |                        |
    |                        attempt to subtract with overflow
 
@@ -26,12 +26,24 @@
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/issue-43197.rs:14:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
 error[E0080]: evaluation of constant expression failed
   --> $DIR/issue-43197.rs:14:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/issue-43197.rs:14:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs
index 7da9256..f919470 100644
--- a/src/test/ui/consts/const-eval/issue-44578.rs
+++ b/src/test/ui/consts/const-eval/issue-44578.rs
@@ -25,5 +25,5 @@
 
 fn main() {
     println!("{}", <Bar<u16, u8> as Foo>::AMT);
-    //~^ ERROR E0080
+    //~^ ERROR evaluation of constant expression failed [E0080]
 }
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index e589126..5c3635e 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -12,11 +12,13 @@
 struct Sum<A,B>(A,B);
 
 impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
-    const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
+    const MAX: u8 = A::MAX + B::MAX;
+    //~^ ERROR any use of this value will cause an error [const_err]
 }
 
 fn foo<T>(_: T) -> &'static u8 {
-    &Sum::<U8,U8>::MAX //~ ERROR E0080
+    &Sum::<U8,U8>::MAX
+    //~^ ERROR E0080
 }
 
 fn main() {
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index f8b017e..2e5167a 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -9,7 +9,7 @@
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814.rs:19:5
+  --> $DIR/issue-50814.rs:20:5
    |
 LL |     &Sum::<U8,U8>::MAX
    |     ^-----------------
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index 2eed8ca..22f863f 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -1,20 +1,23 @@
-// build-fail
+// build-pass
+// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
 // compile-flags: -O
 
-#![deny(const_err)]
+#![warn(const_err)]
 
 fn main() {
     println!("{}", 0u32 - 1);
     let _x = 0u32 - 1;
-    //~^ ERROR const_err
-    println!("{}", 1/(1-1));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(1-1);
-    //~^ ERROR const_err
-    println!("{}", 1/(false as u32));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(false as u32);
-    //~^ ERROR const_err
+    //~^ WARN const_err
+    println!("{}", 1 / (1 - 1));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (1 - 1);
+    //~^ WARN const_err
+    println!("{}", 1 / (false as u32));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (false as u32);
+    //~^ WARN const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
index 8f17ef0..b4330de 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -1,50 +1,60 @@
-error: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:8:14
+warning: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:9:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^ attempt to subtract with overflow
    |
 note: lint level defined here
-  --> $DIR/promoted_errors.rs:4:9
+  --> $DIR/promoted_errors.rs:5:9
    |
-LL | #![deny(const_err)]
+LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:10:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:11:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:10:20
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:11:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:13:14
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:11:20
    |
-LL |     let _x = 1/(1-1);
-   |              ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:15:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:15:14
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:15:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:17:20
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:18:14
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:17:20
    |
-LL |     let _x = 1/(false as u32);
-   |              ^^^^^^^^^^^^^^^^
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
 
-error: aborting due to 7 previous errors
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:17:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:21:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs
index ae680b4..62c77f7 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors2.rs
@@ -1,21 +1,24 @@
-// build-fail
+// build-pass
+// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
 // compile-flags: -C overflow-checks=on -O
 
-#![deny(const_err)]
+#![warn(const_err)]
 
 fn main() {
     println!("{}", 0u32 - 1);
-    //~^ ERROR attempt to subtract with overflow
+    //~^ WARN 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 const_err
-    let _x = 1/(1-1);
-    //~^ ERROR const_err
-    println!("{}", 1/(false as u32));
-    //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR const_err
-    let _x = 1/(false as u32);
-    //~^ ERROR const_err
+    //~^ WARN attempt to subtract with overflow
+    println!("{}", 1 / (1 - 1));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (1 - 1);
+    //~^ WARN const_err
+    println!("{}", 1 / (false as u32));
+    //~^ WARN attempt to divide by zero [const_err]
+    //~| WARN const_err
+    //~| WARN erroneous constant used [const_err]
+    let _x = 1 / (false as u32);
+    //~^ WARN const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr
index 60a3cba..a4dad29 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr
@@ -1,56 +1,66 @@
-error: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:7:20
+warning: attempt to subtract with overflow
+  --> $DIR/promoted_errors2.rs:8:20
    |
 LL |     println!("{}", 0u32 - 1);
    |                    ^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/promoted_errors2.rs:4:9
+  --> $DIR/promoted_errors2.rs:5:9
    |
-LL | #![deny(const_err)]
+LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
-error: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:9:14
+warning: attempt to subtract with overflow
+  --> $DIR/promoted_errors2.rs:10:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:11:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:12:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:11:20
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors2.rs:12:20
    |
-LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:14:14
+warning: erroneous constant used
+  --> $DIR/promoted_errors2.rs:12:20
    |
-LL |     let _x = 1/(1-1);
-   |              ^^^^^^^
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:16:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:16:14
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^
 
-error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:16:20
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:18:20
    |
-LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ dividing by zero
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^
 
-error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:19:14
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors2.rs:18:20
    |
-LL |     let _x = 1/(false as u32);
-   |              ^^^^^^^^^^^^^^^^
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
 
-error: aborting due to 8 previous errors
+warning: erroneous constant used
+  --> $DIR/promoted_errors2.rs:18:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:22:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^
 
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 45ce040..87136a1 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
@@ -5,6 +5,7 @@
     match n {
         0..=10 => {},
         10..=BAR => {}, //~ ERROR could not evaluate constant pattern
+                        //~| ERROR could not evaluate constant pattern
         _ => {},
     }
 }
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 b72a5b8..17f8744 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,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ref_to_int_match.rs:24:1
+  --> $DIR/ref_to_int_match.rs:25:1
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
@@ -12,6 +12,12 @@
 LL |         10..=BAR => {},
    |              ^^^
 
-error: aborting due to 2 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/ref_to_int_match.rs:7:14
+   |
+LL |         10..=BAR => {},
+   |              ^^^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index 80d80a9..c2446d1 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -13,7 +13,7 @@
 LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
 LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
 LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 6 which has size 1
+   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1
 LL | |     mem::transmute(out_of_bounds_ptr)
 LL | | } };
    | |____-
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
index bde7f25..51e80bb 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
@@ -34,7 +34,7 @@
    |              help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `#[warn(invalid_value)]` on by default
-   = note: The never type (`!`) has no valid value
+   = note: the `!` type has no valid value
 
 warning: the type `Empty` does not permit zero-initialization
   --> $DIR/validate_uninhabited_zsts.rs:17:35
@@ -45,7 +45,7 @@
    |                                   this code causes undefined behavior when executed
    |                                   help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: 0-variant enums have no valid value
+   = note: enums with no variants have no valid value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
new file mode 100644
index 0000000..7ced248
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
@@ -0,0 +1,7 @@
+fn main() {}
+
+#[cfg(FALSE)]
+fn container() {
+    const unsafe WhereIsFerris Now() {}
+    //~^ ERROR expected one of `extern` or `fn`
+}
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr
new file mode 100644
index 0000000..5ec9e2a
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `extern` or `fn`, found `WhereIsFerris`
+  --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs:5:18
+   |
+LL |     const unsafe WhereIsFerris Now() {}
+   |                  ^^^^^^^^^^^^^ expected one of `extern` or `fn`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
new file mode 100644
index 0000000..1886bfc
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
@@ -0,0 +1,8 @@
+fn main() {}
+
+#[cfg(FALSE)]
+fn container() {
+    const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
+    //~^ ERROR expected `fn`
+    //~| ERROR `const extern fn` definitions are unstable
+}
diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr
new file mode 100644
index 0000000..cf71ed4d
--- /dev/null
+++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr
@@ -0,0 +1,18 @@
+error: expected `fn`, found `PUT_ANYTHING_YOU_WANT_HERE`
+  --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier.rs:5:25
+   |
+LL |     const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `fn`
+
+error[E0658]: `const extern fn` definitions are unstable
+  --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier.rs:5:5
+   |
+LL |     const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
+   |     ^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/64926
+   = help: add `#![feature(const_extern_fn)]` 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/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
index 2d4175e..df793d7 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -4,17 +4,21 @@
 LL |     random()
    |     ^^^^^^^^
 
-error[E0013]: constant functions cannot refer to statics, use a constant instead
+error[E0013]: constant functions cannot refer to statics
   --> $DIR/const-fn-not-safe-for-const.rs:20:5
    |
 LL |     Y
    |     ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0013]: constant functions cannot refer to statics, use a constant instead
+error[E0013]: constant functions cannot refer to statics
   --> $DIR/const-fn-not-safe-for-const.rs:25:6
    |
 LL |     &Y
    |      ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
index 33abfec..99006a2 100644
--- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -1,7 +1,6 @@
 // run-pass
 
 #![feature(const_mut_refs)]
-#![feature(const_fn)]
 
 struct Foo {
     x: usize
diff --git a/src/test/ui/consts/const_prop_slice_pat_ice.rs b/src/test/ui/consts/const_prop_slice_pat_ice.rs
index 5fec36e..60b06a4 100644
--- a/src/test/ui/consts/const_prop_slice_pat_ice.rs
+++ b/src/test/ui/consts/const_prop_slice_pat_ice.rs
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn main() {
     match &[0, 1] as &[i32] {
diff --git a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
index 7887fd1..6bbbdd9 100644
--- a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
+++ b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
@@ -3,7 +3,6 @@
 // check-pass
 
 #![feature(const_if_match)]
-#![feature(const_fn)]
 
 enum E {
     A,
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
index 9509672..21e3f2a 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate-const-if-match.rs:109:1
+  --> $DIR/feature-gate-const-if-match.rs:108:1
    |
 LL | / fn main() {
 LL | |     let _ = [0; {
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
index e4b6525..00576d5 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
@@ -6,7 +6,6 @@
 
 #![feature(rustc_attrs)]
 #![cfg_attr(if_match, feature(const_if_match))]
-#![feature(const_fn)]
 
 const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const`
     5
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
index e846ee4..d3c6a51 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:11:16
+  --> $DIR/feature-gate-const-if-match.rs:10:16
    |
 LL |   const _: i32 = if true {
    |  ________________^
@@ -13,7 +13,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:17:16
+  --> $DIR/feature-gate-const-if-match.rs:16:16
    |
 LL |   const _: i32 = if let Some(true) = Some(false) {
    |  ________________^
@@ -27,7 +27,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:23:16
+  --> $DIR/feature-gate-const-if-match.rs:22:16
    |
 LL |   const _: i32 = match 1 {
    |  ________________^
@@ -41,7 +41,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:30:13
+  --> $DIR/feature-gate-const-if-match.rs:29:13
    |
 LL |     let x = if true { 0 } else { 1 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +50,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:32:13
+  --> $DIR/feature-gate-const-if-match.rs:31:13
    |
 LL |     let x = match x { 0 => 1, _ => 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:34:5
+  --> $DIR/feature-gate-const-if-match.rs:33:5
    |
 LL |     if let Some(x) = Some(x) { x } else { 1 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:39:13
+  --> $DIR/feature-gate-const-if-match.rs:38:13
    |
 LL |     let x = if true { 0 } else { 1 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:41:13
+  --> $DIR/feature-gate-const-if-match.rs:40:13
    |
 LL |     let x = match x { 0 => 1, _ => 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:43:5
+  --> $DIR/feature-gate-const-if-match.rs:42:5
    |
 LL |     if let Some(x) = Some(x) { x } else { 1 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:48:5
+  --> $DIR/feature-gate-const-if-match.rs:47:5
    |
 LL |     if true { 5 } else { 6 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:52:5
+  --> $DIR/feature-gate-const-if-match.rs:51:5
    |
 LL | /     if let Some(true) = a {
 LL | |         0
@@ -117,7 +117,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:60:5
+  --> $DIR/feature-gate-const-if-match.rs:59:5
    |
 LL | /     match i {
 LL | |         i if i > 10 => i,
@@ -130,7 +130,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:91:17
+  --> $DIR/feature-gate-const-if-match.rs:90:17
    |
 LL |         let x = if y { 0 } else { 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^^
@@ -139,7 +139,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:93:17
+  --> $DIR/feature-gate-const-if-match.rs:92:17
    |
 LL |         let x = match x { 0 => 1, _ => 0 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:95:9
+  --> $DIR/feature-gate-const-if-match.rs:94:9
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:111:17
+  --> $DIR/feature-gate-const-if-match.rs:110:17
    |
 LL |         let x = if false { 0 } else { 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +166,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:113:17
+  --> $DIR/feature-gate-const-if-match.rs:112:17
    |
 LL |         let x = match x { 0 => 1, _ => 0 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -175,7 +175,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:115:9
+  --> $DIR/feature-gate-const-if-match.rs:114:9
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +184,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:68:21
+  --> $DIR/feature-gate-const-if-match.rs:67:21
    |
 LL |     const IF: i32 = if true { 5 } else { 6 };
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:71:25
+  --> $DIR/feature-gate-const-if-match.rs:70:25
    |
 LL |     const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -202,7 +202,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:74:24
+  --> $DIR/feature-gate-const-if-match.rs:73:24
    |
 LL |     const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -211,7 +211,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:79:21
+  --> $DIR/feature-gate-const-if-match.rs:78:21
    |
 LL |     const IF: i32 = if true { 5 } else { 6 };
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +220,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:82:25
+  --> $DIR/feature-gate-const-if-match.rs:81:25
    |
 LL |     const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +229,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:85:24
+  --> $DIR/feature-gate-const-if-match.rs:84:24
    |
 LL |     const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +238,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/feature-gate-const-if-match.rs:115:21
+  --> $DIR/feature-gate-const-if-match.rs:114:21
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |                     ^
diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs
index 4b20a21..8cee2a5 100644
--- a/src/test/ui/consts/control-flow/short-circuit-let.rs
+++ b/src/test/ui/consts/control-flow/short-circuit-let.rs
@@ -4,7 +4,6 @@
 
 #![feature(const_if_match)]
 #![feature(const_panic)]
-#![feature(const_fn)]
 
 const X: i32 = {
     let mut x = 0;
diff --git a/src/test/ui/consts/control-flow/single_variant_match_ice.rs b/src/test/ui/consts/control-flow/single_variant_match_ice.rs
index bb0fce6..823605f 100644
--- a/src/test/ui/consts/control-flow/single_variant_match_ice.rs
+++ b/src/test/ui/consts/control-flow/single_variant_match_ice.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(const_if_match, const_fn)]
+#![feature(const_if_match)]
 
 enum Foo {
     Prob,
diff --git a/src/test/ui/consts/enum-discr-type-err.rs b/src/test/ui/consts/enum-discr-type-err.rs
index d66c4f4..5adb2fa 100644
--- a/src/test/ui/consts/enum-discr-type-err.rs
+++ b/src/test/ui/consts/enum-discr-type-err.rs
@@ -17,6 +17,7 @@
         enum E {
             $( $v = $s::V, )*
             //~^ ERROR mismatched types
+            //~| ERROR mismatched types
         }
     }
 }
diff --git a/src/test/ui/consts/enum-discr-type-err.stderr b/src/test/ui/consts/enum-discr-type-err.stderr
index 848ccf9..9935f88 100644
--- a/src/test/ui/consts/enum-discr-type-err.stderr
+++ b/src/test/ui/consts/enum-discr-type-err.stderr
@@ -15,6 +15,23 @@
 LL |             $( $v = $s::V.try_into().unwrap(), )*
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/enum-discr-type-err.rs:18:21
+   |
+LL |               $( $v = $s::V, )*
+   |                       ^^^^^ expected `isize`, found `i32`
+...
+LL | / mac! {
+LL | |     A = F,
+LL | |     B = T,
+LL | | }
+   | |_- in this macro invocation
+   |
+help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |             $( $v = $s::V.try_into().unwrap(), )*
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/huge-values.rs b/src/test/ui/consts/huge-values.rs
index ab09922..70a5b10 100644
--- a/src/test/ui/consts/huge-values.rs
+++ b/src/test/ui/consts/huge-values.rs
@@ -1,6 +1,10 @@
 // build-pass
 // ignore-32bit
 
+// This test is a canary test that will essentially not compile in a reasonable time frame
+// (so it'll take hours) if any of the optimizations regress. With the optimizations, these compile
+// in milliseconds just as if the length were set to `1`.
+
 #[derive(Clone, Copy)]
 struct Foo;
 
@@ -8,4 +12,6 @@
     let _ = [(); 4_000_000_000];
     let _ = [0u8; 4_000_000_000];
     let _ = [Foo; 4_000_000_000];
+    let _ = [(Foo, (), Foo, ((), Foo, [0; 0])); 4_000_000_000];
+    let _ = [[0; 0]; 4_000_000_000];
 }
diff --git a/src/test/ui/consts/issue-67529.rs b/src/test/ui/consts/issue-67529.rs
new file mode 100644
index 0000000..df4bc66
--- /dev/null
+++ b/src/test/ui/consts/issue-67529.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z mir-opt-level=2
+// run-pass
+
+struct Baz<T: ?Sized> {
+    a: T
+}
+
+fn main() {
+    let d : Baz<[i32; 4]> = Baz { a: [1,2,3,4] };
+    assert_eq!([1, 2, 3, 4], d.a);
+}
diff --git a/src/test/ui/consts/issue-67640.rs b/src/test/ui/consts/issue-67640.rs
new file mode 100644
index 0000000..bc0ee8d
--- /dev/null
+++ b/src/test/ui/consts/issue-67640.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Z mir-opt-level=3
+// run-pass
+
+struct X {
+    x: isize
+}
+
+fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
+    let r = a.x + *b + c;
+    a.x = 0;
+    *b = 10;
+    return r;
+}
+
+fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
+
+pub fn main() {
+    let mut a = X {x: 1};
+    let mut b = 2;
+    let c = 3;
+    assert_eq!(f1(&mut a, &mut b, c), 6);
+    assert_eq!(a.x, 0);
+    assert_eq!(f2(a.x, |_| a.x = 50), 0);
+}
diff --git a/src/test/ui/consts/issue-67641.rs b/src/test/ui/consts/issue-67641.rs
new file mode 100644
index 0000000..f50fba2
--- /dev/null
+++ b/src/test/ui/consts/issue-67641.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Z mir-opt-level=2
+// run-pass
+
+use std::cell::Cell;
+
+#[derive(Debug)]
+struct B<'a> {
+    a: [Cell<Option<&'a B<'a>>>; 2]
+}
+
+impl<'a> B<'a> {
+    fn new() -> B<'a> {
+        B { a: [Cell::new(None), Cell::new(None)] }
+    }
+}
+
+fn f() {
+    let b2 = B::new();
+    b2.a[0].set(Some(&b2));
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/consts/issue-67696-const-prop-ice.rs b/src/test/ui/consts/issue-67696-const-prop-ice.rs
new file mode 100644
index 0000000..ad52608
--- /dev/null
+++ b/src/test/ui/consts/issue-67696-const-prop-ice.rs
@@ -0,0 +1,20 @@
+// check-pass
+// compile-flags: --emit=mir,link
+// Checks that we don't ICE due to attempting to run const prop
+// on a function with unsatisifable 'where' clauses
+
+#![allow(unused)]
+
+trait A {
+    fn foo(&self) -> Self where Self: Copy;
+}
+
+impl A for [fn(&())] {
+    fn foo(&self) -> Self where Self: Copy { *(&[] as &[_]) }
+}
+
+impl A for i32 {
+    fn foo(&self) -> Self { 3 }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-67862.rs b/src/test/ui/consts/issue-67862.rs
new file mode 100644
index 0000000..84f7215
--- /dev/null
+++ b/src/test/ui/consts/issue-67862.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z mir-opt-level=2
+// run-pass
+
+fn e220() -> (i64, i64) {
+    #[inline(never)]
+    fn get_displacement() -> [i64; 2] {
+        [139776, 963904]
+    }
+
+    let res = get_displacement();
+    match (&res[0], &res[1]) {
+        (arg0, arg1) => (*arg0, *arg1),
+    }
+}
+
+fn main() {
+    assert_eq!(e220(), (139776, 963904));
+}
diff --git a/src/test/ui/consts/issue-68264-overflow.rs b/src/test/ui/consts/issue-68264-overflow.rs
new file mode 100644
index 0000000..8f21e06
--- /dev/null
+++ b/src/test/ui/consts/issue-68264-overflow.rs
@@ -0,0 +1,43 @@
+// check-pass
+// compile-flags: --emit=mir,link
+// Regression test for issue #68264
+// Checks that we don't encounter overflow
+// when running const-prop on functions with
+// complicated bounds
+pub trait Query {}
+
+pub trait AsQuery {
+    type Query: Query;
+}
+pub trait Table: AsQuery + Sized {}
+
+pub trait LimitDsl {
+    type Output;
+}
+
+pub(crate) trait LoadQuery<Conn, U>: RunQueryDsl<Conn> {}
+
+impl<T: Query> AsQuery for T {
+    type Query = Self;
+}
+
+impl<T> LimitDsl for T
+where
+    T: Table,
+    T::Query: LimitDsl,
+{
+    type Output = <T::Query as LimitDsl>::Output;
+}
+
+pub(crate) trait RunQueryDsl<Conn>: Sized {
+    fn first<U>(self, _conn: &Conn) -> U
+    where
+        Self: LimitDsl,
+        Self::Output: LoadQuery<Conn, U>,
+    {
+        // Overflow is caused by this function body
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs
index 1c13bfc..1e49543 100644
--- a/src/test/ui/consts/match_ice.rs
+++ b/src/test/ui/consts/match_ice.rs
@@ -10,6 +10,7 @@
     match C {
         C => {}
         //~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
+        //~| ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
     }
     const K: &T = &T;
     match K { //~ ERROR non-exhaustive patterns: `&T` not covered
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
index bf0bd3a..b25ac09 100644
--- a/src/test/ui/consts/match_ice.stderr
+++ b/src/test/ui/consts/match_ice.stderr
@@ -5,7 +5,7 @@
    |         ^
 
 error[E0004]: non-exhaustive patterns: `&T` not covered
-  --> $DIR/match_ice.rs:15:11
+  --> $DIR/match_ice.rs:16:11
    |
 LL | struct T;
    | --------- `T` defined here
@@ -15,6 +15,12 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error: aborting due to 2 previous errors
+error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match_ice.rs:11:9
+   |
+LL |         C => {}
+   |         ^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
index e07db3f..edbf0e0 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
@@ -28,6 +28,7 @@
 static mut MUTABLE: u32 = 0;
 const READ_MUT: u32 = unsafe { MUTABLE }; //~ WARN any use of this value will cause an error
 //~^ WARN skipping const checks
+//~| WARN skipping const checks
 
 // ok some day perhaps
 const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
index eae76c1..243efbb 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
@@ -29,7 +29,13 @@
    |                                ^^^^^^^
 
 warning: skipping const checks
-  --> $DIR/const_refers_to_static.rs:35:6
+  --> $DIR/const_refers_to_static.rs:29:32
+   |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+   |                                ^^^^^^^
+
+warning: skipping const checks
+  --> $DIR/const_refers_to_static.rs:36:6
    |
 LL |     &FOO
    |      ^^^
@@ -84,7 +90,7 @@
    |                                constant accesses static
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const_refers_to_static.rs:33:1
+  --> $DIR/const_refers_to_static.rs:34:1
    |
 LL | / const READ_IMMUT: &usize = {
 LL | |     static FOO: usize = 0;
diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr
index 2cdeb59..2439d52 100644
--- a/src/test/ui/consts/miri_unleashed/drop.stderr
+++ b/src/test/ui/consts/miri_unleashed/drop.stderr
@@ -7,17 +7,17 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
    |
-LL | / unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
+LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 LL | |     // Code here does not matter - this is replaced by the
 LL | |     // real drop glue by the compiler.
-LL | |     real_drop_in_place(to_drop)
+LL | |     drop_in_place(to_drop)
 LL | | }
    | |_^ calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop`
    | 
   ::: $DIR/drop.rs:23:1
    |
 LL |   };
-   |   - inside call to `std::ptr::real_drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1
+   |   - inside call to `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
index 3493b7c..a316d8f 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr
@@ -10,8 +10,8 @@
 LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:357:17
+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/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
index c148842..c292fce 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
@@ -7,7 +7,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 could observe that mutation.', src/librustc_mir/interpret/intern.rs:LL:CC
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+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/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
index 32a713e..cfb57d2 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
@@ -11,5 +11,7 @@
 //~^ WARN any use of this value will cause an error
 
 fn main() {
-    println!("{:?}", C); //~ ERROR: evaluation of constant expression failed
+    println!("{:?}", C);
+    //~^ ERROR: evaluation of constant expression failed
+    //~| WARN: erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
index 75f532a..6a7df85 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
@@ -24,6 +24,12 @@
 LL |     println!("{:?}", C);
    |                      ^ referenced constant has errors
 
+warning: erroneous constant used
+  --> $DIR/non_const_fn.rs:14:22
+   |
+LL |     println!("{:?}", C);
+   |                      ^ referenced constant has errors
+
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/raw_pointer_promoted.rs b/src/test/ui/consts/raw_pointer_promoted.rs
new file mode 100644
index 0000000..4c62ad4
--- /dev/null
+++ b/src/test/ui/consts/raw_pointer_promoted.rs
@@ -0,0 +1,5 @@
+// check-pass
+
+pub const FOO: &'static *const i32 = &(&0 as _);
+
+fn main() {}
diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr
index 2fb9977..599d1d7 100644
--- a/src/test/ui/consts/too_generic_eval_ice.stderr
+++ b/src/test/ui/consts/too_generic_eval_ice.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `HOST_SIZE` found for type `Foo<A, B>` in the current scope
+error[E0599]: no associated item named `HOST_SIZE` found for struct `Foo<A, B>` in the current scope
   --> $DIR/too_generic_eval_ice.rs:7:19
    |
 LL | pub struct Foo<A, B>(A, B);
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
index b5d2b43..2817abf 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
@@ -8,6 +8,7 @@
 fn main() {
     match &b""[..] {
         ZST => {} //~ ERROR could not evaluate constant pattern
+                  //~| ERROR could not evaluate constant pattern
     }
 }
 
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
index 5f84204..296a55e 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:14:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:15:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -15,7 +15,7 @@
    |         ^^^
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:14:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:15:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
@@ -23,6 +23,12 @@
    = note: source type: `usize` (word size)
    = note: target type: `&'static [u8]` (2 * word size)
 
-error: aborting due to 3 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9
+   |
+LL |         ZST => {}
+   |         ^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/consts/validate_never_arrays.rs b/src/test/ui/consts/validate_never_arrays.rs
index 9610b7b..c7144f05 100644
--- a/src/test/ui/consts/validate_never_arrays.rs
+++ b/src/test/ui/consts/validate_never_arrays.rs
@@ -1,5 +1,9 @@
 #![feature(const_raw_ptr_deref, never_type)]
 
-const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
+const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
+const _: &[!; 0] = unsafe { &*(1_usize as *const [!; 0]) }; // ok
+const _: &[!] = unsafe { &*(1_usize as *const [!; 0]) }; // ok
+const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
+const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior
 
 fn main() {}
diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr
index c4c7a33..cb995b8 100644
--- a/src/test/ui/consts/validate_never_arrays.stderr
+++ b/src/test/ui/consts/validate_never_arrays.stderr
@@ -1,11 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:3:1
    |
-LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
+LL | const _: &[!; 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 rustc repository if you believe it should not be considered undefined behavior.
 
-error: aborting due to previous error
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/validate_never_arrays.rs:6:1
+   |
+LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type 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 rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/validate_never_arrays.rs:7:1
+   |
+LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type 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 rustc repository if you believe it should not be considered undefined behavior.
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/zst_no_llvm_alloc.rs b/src/test/ui/consts/zst_no_llvm_alloc.rs
index 5d77935..2a41f70 100644
--- a/src/test/ui/consts/zst_no_llvm_alloc.rs
+++ b/src/test/ui/consts/zst_no_llvm_alloc.rs
@@ -7,13 +7,15 @@
 
 fn main() {
     let x: &'static () = &();
-    assert_eq!(x as *const () as usize, 1);
+    assert_ne!(x as *const () as usize, 1);
     let x: &'static Foo = &Foo;
-    assert_eq!(x as *const Foo as usize, 4);
+    assert_ne!(x as *const Foo as usize, 4);
 
     // statics must have a unique address
     assert_ne!(&FOO as *const Foo as usize, 4);
 
-    assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
-    assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
+    // FIXME this two tests should be assert_eq!
+    // this stopped working since we are promoting to constants instead of statics
+    assert_ne!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
+    assert_ne!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
 }
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index 054bd09..c95e8d2 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Foo` in the current scope
+error[E0599]: no method named `clone` found for struct `Foo` in the current scope
   --> $DIR/copy-a-resource.rs:18:16
    |
 LL | struct Foo {
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
index 6175b7d..b2edc1a 100644
--- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.rs
@@ -3,6 +3,7 @@
 
 trait Foo<X = Box<dyn Foo>> {
     //~^ ERROR cycle detected
+    //~| ERROR cycle detected
 }
 
 fn main() { }
diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
index e89d257..6b38d85 100644
--- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
+++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
@@ -11,6 +11,19 @@
 LL | trait Foo<X = Box<dyn Foo>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0391]: cycle detected when processing `Foo::X`
+  --> $DIR/cycle-trait-default-type-trait.rs:4:23
+   |
+LL | trait Foo<X = Box<dyn Foo>> {
+   |                       ^^^
+   |
+   = note: ...which again requires processing `Foo::X`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/cycle-trait-default-type-trait.rs:4:1
+   |
+LL | trait Foo<X = Box<dyn Foo>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr
new file mode 100644
index 0000000..7a28c64
--- /dev/null
+++ b/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr
@@ -0,0 +1,28 @@
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:11:9
+   |
+LL |         2.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
diff --git a/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr
new file mode 100644
index 0000000..4fff3a8
--- /dev/null
+++ b/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr
@@ -0,0 +1,37 @@
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:11:9
+   |
+LL |         2.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:7:9
+   |
+LL |         1.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/deduplicate-diagnostics-2.rs:11:9
+   |
+LL |         2.0 => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
diff --git a/src/test/ui/deduplicate-diagnostics-2.rs b/src/test/ui/deduplicate-diagnostics-2.rs
new file mode 100644
index 0000000..f46a7c0
--- /dev/null
+++ b/src/test/ui/deduplicate-diagnostics-2.rs
@@ -0,0 +1,17 @@
+// build-pass
+// revisions: duplicate deduplicate
+//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes
+
+fn main() {
+    match 0.0 {
+        1.0 => {} //~ WARNING floating-point types cannot be used in patterns
+                  //~| WARNING this was previously accepted
+                  //~| WARNING floating-point types cannot be used in patterns
+                  //~| WARNING this was previously accepted
+        2.0 => {} //~ WARNING floating-point types cannot be used in patterns
+                  //~| WARNING this was previously accepted
+                  //[duplicate]~| WARNING floating-point types cannot be used in patterns
+                  //[duplicate]~| WARNING this was previously accepted
+        _ => {}
+    }
+}
diff --git a/src/test/ui/deduplicate-diagnostics.deduplicate.stderr b/src/test/ui/deduplicate-diagnostics.deduplicate.stderr
index 1acfce5..5df2c68 100644
--- a/src/test/ui/deduplicate-diagnostics.deduplicate.stderr
+++ b/src/test/ui/deduplicate-diagnostics.deduplicate.stderr
@@ -1,8 +1,15 @@
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
+
 error: cannot find derive macro `Unresolved` in this scope
   --> $DIR/deduplicate-diagnostics.rs:4:10
    |
 LL | #[derive(Unresolved)]
    |          ^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/deduplicate-diagnostics.duplicate.stderr b/src/test/ui/deduplicate-diagnostics.duplicate.stderr
index 325da3b..3b100b5 100644
--- a/src/test/ui/deduplicate-diagnostics.duplicate.stderr
+++ b/src/test/ui/deduplicate-diagnostics.duplicate.stderr
@@ -1,3 +1,9 @@
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
+
 error: cannot find derive macro `Unresolved` in this scope
   --> $DIR/deduplicate-diagnostics.rs:4:10
    |
@@ -10,5 +16,18 @@
 LL | #[derive(Unresolved)]
    |          ^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
 
+error[E0452]: malformed lint attribute input
+  --> $DIR/deduplicate-diagnostics.rs:8:8
+   |
+LL | #[deny("literal")]
+   |        ^^^^^^^^^ bad attribute argument
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/deduplicate-diagnostics.rs b/src/test/ui/deduplicate-diagnostics.rs
index 4a1f503..c5d41ff 100644
--- a/src/test/ui/deduplicate-diagnostics.rs
+++ b/src/test/ui/deduplicate-diagnostics.rs
@@ -1,8 +1,11 @@
 // revisions: duplicate deduplicate
-//[duplicate] compile-flags: -Z deduplicate-diagnostics=no
+//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes
 
 #[derive(Unresolved)] //~ ERROR cannot find derive macro `Unresolved` in this scope
                       //[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope
 struct S;
 
+#[deny("literal")] //~ ERROR malformed lint attribute input
+                   //[duplicate]~| ERROR malformed lint attribute input
+                   //[duplicate]~| ERROR malformed lint attribute input
 fn main() {}
diff --git a/src/test/ui/deprecation/deprecated-macro_escape-inner.rs b/src/test/ui/deprecation/deprecated-macro_escape-inner.rs
index 957e839..e2957c4 100644
--- a/src/test/ui/deprecation/deprecated-macro_escape-inner.rs
+++ b/src/test/ui/deprecation/deprecated-macro_escape-inner.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 mod foo {
-    #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+    #![macro_escape] //~ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
 }
 
 fn main() {
diff --git a/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr b/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr
index 1b69270..4b0fc07 100644
--- a/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr
+++ b/src/test/ui/deprecation/deprecated-macro_escape-inner.stderr
@@ -1,8 +1,8 @@
-warning: macro_escape is a deprecated synonym for macro_use
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/deprecated-macro_escape-inner.rs:4:5
    |
 LL |     #![macro_escape]
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: consider an outer attribute, `#[macro_use]` mod ...
+   = help: try an outer attribute: `#[macro_use]`
 
diff --git a/src/test/ui/deprecation/deprecated-macro_escape.rs b/src/test/ui/deprecation/deprecated-macro_escape.rs
index 1b82a99..4a89b40 100644
--- a/src/test/ui/deprecation/deprecated-macro_escape.rs
+++ b/src/test/ui/deprecation/deprecated-macro_escape.rs
@@ -1,8 +1,6 @@
 // run-pass
 
-#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
-mod foo {
-}
+#[macro_escape] //~ WARNING `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
+mod foo {}
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/deprecation/deprecated-macro_escape.stderr b/src/test/ui/deprecation/deprecated-macro_escape.stderr
index b76d6d7..7009408 100644
--- a/src/test/ui/deprecation/deprecated-macro_escape.stderr
+++ b/src/test/ui/deprecation/deprecated-macro_escape.stderr
@@ -1,4 +1,4 @@
-warning: macro_escape is a deprecated synonym for macro_use
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/deprecated-macro_escape.rs:3:1
    |
 LL | #[macro_escape]
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index 038de80..2083a1d 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Bar<NotClone>` in the current scope
+error[E0599]: no method named `clone` found for struct `Bar<NotClone>` in the current scope
   --> $DIR/derive-assoc-type-not-impl.rs:18:30
    |
 LL | struct Bar<T: Foo> {
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
index 2a5d09d..beef639 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs
@@ -10,7 +10,11 @@
 #[derive(PartialOrd,PartialEq)]
 enum Enum {
    A {
-     x: Error //~ ERROR
+     x: Error //~ ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
+              //~| ERROR can't compare `Error` with `Error`
    }
 }
 
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
index 3f669c2..80b896f 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:13:6
+   |
+LL |      x: Error
+   |      ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.rs b/src/test/ui/derives/derives-span-PartialOrd-enum.rs
index e69c182..b02828d 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum.rs
@@ -10,7 +10,11 @@
 #[derive(PartialOrd,PartialEq)]
 enum Enum {
    A(
-     Error //~ ERROR
+     Error //~ ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
+           //~| ERROR can't compare `Error` with `Error`
      )
 }
 
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
index a78af9e..f12038f 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-enum.rs:13:6
+   |
+LL |      Error
+   |      ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.rs b/src/test/ui/derives/derives-span-PartialOrd-struct.rs
index b5d1df9..bfcfc3d 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-struct.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-struct.rs
@@ -9,7 +9,11 @@
 
 #[derive(PartialOrd,PartialEq)]
 struct Struct {
-    x: Error //~ ERROR
+    x: Error //~ ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
+             //~| ERROR can't compare `Error` with `Error`
 }
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
index 8e85f1a..dbb0147 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-struct.rs:12:5
+   |
+LL |     x: Error
+   |     ^^^^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
index 7dfb33b..c8bdd64 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
+++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.rs
@@ -9,7 +9,11 @@
 
 #[derive(PartialOrd,PartialEq)]
 struct Struct(
-    Error //~ ERROR
+    Error //~ ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
+          //~| ERROR can't compare `Error` with `Error`
 );
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
index bf91578..f6f1694 100644
--- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
+++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Error` with `Error`
+  --> $DIR/derives-span-PartialOrd-tuple-struct.rs:12:5
+   |
+LL |     Error
+   |     ^^^^^ no implementation for `Error < Error` and `Error > Error`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Error`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/derives/deriving-bounds.rs b/src/test/ui/derives/deriving-bounds.rs
index 52659bd..95d4404 100644
--- a/src/test/ui/derives/deriving-bounds.rs
+++ b/src/test/ui/derives/deriving-bounds.rs
@@ -1,9 +1,11 @@
 #[derive(Send)]
 //~^ ERROR cannot find derive macro `Send` in this scope
+//~| ERROR cannot find derive macro `Send` in this scope
 struct Test;
 
 #[derive(Sync)]
 //~^ ERROR cannot find derive macro `Sync` in this scope
+//~| ERROR cannot find derive macro `Sync` in this scope
 struct Test1;
 
 pub fn main() {}
diff --git a/src/test/ui/derives/deriving-bounds.stderr b/src/test/ui/derives/deriving-bounds.stderr
index b18df35..74ca372 100644
--- a/src/test/ui/derives/deriving-bounds.stderr
+++ b/src/test/ui/derives/deriving-bounds.stderr
@@ -1,11 +1,23 @@
 error: cannot find derive macro `Sync` in this scope
-  --> $DIR/deriving-bounds.rs:5:10
+  --> $DIR/deriving-bounds.rs:6:10
    |
 LL | #[derive(Sync)]
    |          ^^^^
    |
 note: unsafe traits like `Sync` should be implemented explicitly
-  --> $DIR/deriving-bounds.rs:5:10
+  --> $DIR/deriving-bounds.rs:6:10
+   |
+LL | #[derive(Sync)]
+   |          ^^^^
+
+error: cannot find derive macro `Sync` in this scope
+  --> $DIR/deriving-bounds.rs:6:10
+   |
+LL | #[derive(Sync)]
+   |          ^^^^
+   |
+note: unsafe traits like `Sync` should be implemented explicitly
+  --> $DIR/deriving-bounds.rs:6:10
    |
 LL | #[derive(Sync)]
    |          ^^^^
@@ -22,5 +34,17 @@
 LL | #[derive(Send)]
    |          ^^^^
 
-error: aborting due to 2 previous errors
+error: cannot find derive macro `Send` in this scope
+  --> $DIR/deriving-bounds.rs:1:10
+   |
+LL | #[derive(Send)]
+   |          ^^^^
+   |
+note: unsafe traits like `Send` should be implemented explicitly
+  --> $DIR/deriving-bounds.rs:1:10
+   |
+LL | #[derive(Send)]
+   |          ^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.rs b/src/test/ui/derives/deriving-meta-unknown-trait.rs
index f4a6f3f..d1af5b4 100644
--- a/src/test/ui/derives/deriving-meta-unknown-trait.rs
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.rs
@@ -1,5 +1,10 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 #[derive(Eqr)]
 //~^ ERROR cannot find derive macro `Eqr` in this scope
+//~| ERROR cannot find derive macro `Eqr` in this scope
 struct Foo;
 
 pub fn main() {}
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.stderr b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
index 1b8e689..ead1313 100644
--- a/src/test/ui/derives/deriving-meta-unknown-trait.stderr
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
@@ -1,8 +1,24 @@
 error: cannot find derive macro `Eqr` in this scope
-  --> $DIR/deriving-meta-unknown-trait.rs:1:10
+  --> $DIR/deriving-meta-unknown-trait.rs:5:10
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+   | 
+  ::: $SRC_DIR/libcore/cmp.rs:LL:COL
+   |
+LL | pub macro Eq($item:item) {
+   | ------------------------ similarly named derive macro `Eq` defined here
 
-error: aborting due to previous error
+error: cannot find derive macro `Eqr` in this scope
+  --> $DIR/deriving-meta-unknown-trait.rs:5:10
+   |
+LL | #[derive(Eqr)]
+   |          ^^^ help: a derive macro with a similar name exists: `Eq`
+   | 
+  ::: $SRC_DIR/libcore/cmp.rs:LL:COL
+   |
+LL | pub macro Eq($item:item) {
+   | ------------------------ similarly named derive macro `Eq` defined here
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/derives/deriving-primitive.rs b/src/test/ui/derives/deriving-primitive.rs
index c7098d4..1173eca 100644
--- a/src/test/ui/derives/deriving-primitive.rs
+++ b/src/test/ui/derives/deriving-primitive.rs
@@ -1,4 +1,5 @@
 #[derive(FromPrimitive)] //~ ERROR cannot find derive macro `FromPrimitive` in this scope
+                         //~| ERROR cannot find derive macro `FromPrimitive` in this scope
 enum Foo {}
 
 fn main() {}
diff --git a/src/test/ui/derives/deriving-primitive.stderr b/src/test/ui/derives/deriving-primitive.stderr
index d1b4449..ca64c9e 100644
--- a/src/test/ui/derives/deriving-primitive.stderr
+++ b/src/test/ui/derives/deriving-primitive.stderr
@@ -4,5 +4,11 @@
 LL | #[derive(FromPrimitive)]
    |          ^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: cannot find derive macro `FromPrimitive` in this scope
+  --> $DIR/deriving-primitive.rs:1:10
+   |
+LL | #[derive(FromPrimitive)]
+   |          ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/destructure-trait-ref.rs b/src/test/ui/destructure-trait-ref.rs
index fb92196..34e7cad 100644
--- a/src/test/ui/destructure-trait-ref.rs
+++ b/src/test/ui/destructure-trait-ref.rs
@@ -33,12 +33,10 @@
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
     //~| found reference `&_`
-    //~| expected trait `T`, found reference
     let &&&x = &(&1isize as &dyn T);
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
     //~| found reference `&_`
-    //~| expected trait `T`, found reference
     let box box x = box 1isize as Box<dyn T>;
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr
index c78166f..f99bf2f 100644
--- a/src/test/ui/destructure-trait-ref.stderr
+++ b/src/test/ui/destructure-trait-ref.stderr
@@ -22,31 +22,31 @@
 LL |     let &&x = &1isize as &dyn T;
    |          ^^
    |          |
-   |          expected trait `T`, found reference
+   |          expected trait object `dyn T`, found reference
    |          help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/destructure-trait-ref.rs:37:11
+  --> $DIR/destructure-trait-ref.rs:36:11
    |
 LL |     let &&&x = &(&1isize as &dyn T);
    |           ^^
    |           |
-   |           expected trait `T`, found reference
+   |           expected trait object `dyn T`, found reference
    |           help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/destructure-trait-ref.rs:42:13
+  --> $DIR/destructure-trait-ref.rs:40:13
    |
 LL |     let box box x = box 1isize as Box<dyn T>;
    |             ^^^^^   ------------------------ this expression has type `std::boxed::Box<dyn T>`
    |             |
-   |             expected trait `T`, found struct `std::boxed::Box`
+   |             expected trait object `dyn T`, found struct `std::boxed::Box`
    |
    = note: expected trait object `dyn T`
                     found struct `std::boxed::Box<_>`
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.rs b/src/test/ui/did_you_mean/bad-assoc-pat.rs
index 7e7ba59..3f912f7 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.rs
@@ -2,25 +2,25 @@
     match 0u8 {
         [u8]::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `[u8]` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
         (u8, u8)::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `(u8, u8)` in the current sco
+        //~| ERROR no associated item named `AssocItem` found
         _::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `_` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
     match &0u8 {
         &(u8,)::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `(u8,)` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
 }
 
 macro_rules! pat {
     ($ty: ty) => ($ty::AssocItem)
     //~^ ERROR missing angle brackets in associated item path
-    //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+    //~| ERROR no associated item named `AssocItem` found
 }
 macro_rules! ty {
     () => (u8)
@@ -31,6 +31,6 @@
         pat!(u8) => {}
         ty!()::AssocItem => {}
         //~^ ERROR missing angle brackets in associated item path
-        //~| ERROR no associated item named `AssocItem` found for type `u8` in the current scope
+        //~| ERROR no associated item named `AssocItem` found
     }
 }
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
index 59b8654..3f1946b 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
@@ -37,13 +37,13 @@
 LL |         pat!(u8) => {}
    |         -------- in this macro invocation
 
-error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope
+error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope
   --> $DIR/bad-assoc-pat.rs:3:15
    |
 LL |         [u8]::AssocItem => {}
    |               ^^^^^^^^^ associated item not found in `[u8]`
 
-error[E0599]: no associated item named `AssocItem` found for type `(u8, u8)` in the current scope
+error[E0599]: no associated item named `AssocItem` found for tuple `(u8, u8)` in the current scope
   --> $DIR/bad-assoc-pat.rs:6:19
    |
 LL |         (u8, u8)::AssocItem => {}
@@ -55,7 +55,7 @@
 LL |         _::AssocItem => {}
    |            ^^^^^^^^^ associated item not found in `_`
 
-error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope
+error[E0599]: no associated item named `AssocItem` found for tuple `(u8,)` in the current scope
   --> $DIR/bad-assoc-pat.rs:14:17
    |
 LL |         &(u8,)::AssocItem => {}
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
index 0ae64ed..7d3c99b 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
@@ -59,7 +59,7 @@
   --> $DIR/bad-assoc-ty.rs:1:10
    |
 LL | type A = [u8; 4]::AssocTy;
-   |          ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; _] as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; 4] as Trait>::AssocTy`
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:5:10
diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs
index ea21592..60633c6 100644
--- a/src/test/ui/did_you_mean/issue-40006.rs
+++ b/src/test/ui/did_you_mean/issue-40006.rs
@@ -35,5 +35,5 @@
 }
 
 fn main() {
-    S.hello_method(); //~ no method named `hello_method` found for type `S` in the current scope
+    S.hello_method(); //~ no method named `hello_method` found
 }
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index d1e9950..072e61f 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -56,7 +56,7 @@
 LL |     pub hello_method(&self) {
    |        ^ missing `fn`, `type`, or `const`
 
-error[E0599]: no method named `hello_method` found for type `S` in the current scope
+error[E0599]: no method named `hello_method` found for struct `S` in the current scope
   --> $DIR/issue-40006.rs:38:7
    |
 LL | struct S;
diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs
index 1893355..e4e94bb 100644
--- a/src/test/ui/did_you_mean/issue-40396.rs
+++ b/src/test/ui/did_you_mean/issue-40396.rs
@@ -1,8 +1,8 @@
 fn main() {
     (0..13).collect<Vec<i32>>();
-    //~^ ERROR chained comparison
+    //~^ ERROR comparison operators cannot be chained
     Vec<i32>::new();
-    //~^ ERROR chained comparison
+    //~^ ERROR comparison operators cannot be chained
     (0..13).collect<Vec<i32>();
-    //~^ ERROR chained comparison
+    //~^ ERROR comparison operators cannot be chained
 }
diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr
index 749d109..f952136 100644
--- a/src/test/ui/did_you_mean/issue-40396.stderr
+++ b/src/test/ui/did_you_mean/issue-40396.stderr
@@ -1,15 +1,23 @@
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/issue-40396.rs:2:20
    |
 LL |     (0..13).collect<Vec<i32>>();
    |                    ^^^^^
    |
+help: split the comparison into two...
+   |
+LL |     (0..13).collect < Vec && Vec <i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     ((0..13).collect < Vec) <i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: use `::<...>` instead of `<...>` to specify type arguments
    |
 LL |     (0..13).collect::<Vec<i32>>();
    |                    ^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/issue-40396.rs:4:8
    |
 LL |     Vec<i32>::new();
@@ -20,12 +28,20 @@
 LL |     Vec::<i32>::new();
    |        ^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/issue-40396.rs:6:20
    |
 LL |     (0..13).collect<Vec<i32>();
    |                    ^^^^^
    |
+help: split the comparison into two...
+   |
+LL |     (0..13).collect < Vec && Vec <i32>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     ((0..13).collect < Vec) <i32>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: use `::<...>` instead of `<...>` to specify type arguments
    |
 LL |     (0..13).collect::<Vec<i32>();
diff --git a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
index 705c909..d05d6d1 100644
--- a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
+++ b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
@@ -4,11 +4,11 @@
 LL |     while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") {
    |                 ^
    |
-help: try adding parentheses to match on a tuple..
+help: try adding parentheses to match on a tuple...
    |
 LL |     while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") {
    |               ^^^^^^^^^^^^
-help: ..or a vertical bar to match on multiple alternatives
+help: ...or a vertical bar to match on multiple alternatives
    |
 LL |     while let b1 | b2 | b3 = reading_frame.next().expect("there should be a start codon") {
    |               ^^^^^^^^^^^^
@@ -19,11 +19,11 @@
 LL |     if let b1, b2, b3 = reading_frame.next().unwrap() {
    |              ^
    |
-help: try adding parentheses to match on a tuple..
+help: try adding parentheses to match on a tuple...
    |
 LL |     if let (b1, b2, b3) = reading_frame.next().unwrap() {
    |            ^^^^^^^^^^^^
-help: ..or a vertical bar to match on multiple alternatives
+help: ...or a vertical bar to match on multiple alternatives
    |
 LL |     if let b1 | b2 | b3 = reading_frame.next().unwrap() {
    |            ^^^^^^^^^^^^
@@ -34,11 +34,11 @@
 LL |         Nucleotide::Adenine, Nucleotide::Cytosine, _ => true
    |                            ^
    |
-help: try adding parentheses to match on a tuple..
+help: try adding parentheses to match on a tuple...
    |
 LL |         (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: ..or a vertical bar to match on multiple alternatives
+help: ...or a vertical bar to match on multiple alternatives
    |
 LL |         Nucleotide::Adenine | Nucleotide::Cytosine | _ => true
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,11 +49,11 @@
 LL |     for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
    |          ^
    |
-help: try adding parentheses to match on a tuple..
+help: try adding parentheses to match on a tuple...
    |
 LL |     for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) {
    |         ^^^^^^^^^^^^^^^
-help: ..or a vertical bar to match on multiple alternatives
+help: ...or a vertical bar to match on multiple alternatives
    |
 LL |     for x | _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
    |         ^^^^^^^^^^^^^^
@@ -64,11 +64,11 @@
 LL |     for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
    |          ^
    |
-help: try adding parentheses to match on a tuple..
+help: try adding parentheses to match on a tuple...
    |
 LL |     for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^
-help: ..or a vertical bar to match on multiple alternatives
+help: ...or a vertical bar to match on multiple alternatives
    |
 LL |     for x | y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
    |         ^^^^^^^^^^^^^^^^^^^^^^
@@ -79,11 +79,11 @@
 LL |     let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
    |              ^
    |
-help: try adding parentheses to match on a tuple..
+help: try adding parentheses to match on a tuple...
    |
 LL |     let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
    |         ^^^^^^^^^^^^
-help: ..or a vertical bar to match on multiple alternatives
+help: ...or a vertical bar to match on multiple alternatives
    |
 LL |     let women | men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
    |         ^^^^^^^^^^^
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
index 44421b0..467daef 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
@@ -5,8 +5,10 @@
     let b = false;
 
     let _ = a and b; //~ ERROR `and` is not a logical operator
+                     //~| ERROR `and` is not a logical operator
 
     if a and b { //~ ERROR `and` is not a logical operator
+                 //~| ERROR `and` is not a logical operator
         println!("both");
     }
 
@@ -18,8 +20,10 @@
     let b = false;
 
     let _ = a or b; //~ ERROR `or` is not a logical operator
+                    //~| ERROR `or` is not a logical operator
 
     if a or b { //~ ERROR `or` is not a logical operator
+                //~| ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -28,6 +32,7 @@
     let a = true;
     let b = false;
     if (a and b) {  //~ ERROR `and` is not a logical operator
+                    //~| ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -36,6 +41,7 @@
     let a = true;
     let b = false;
     if (a or b) {  //~ ERROR `or` is not a logical operator
+                   //~| ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -44,6 +50,7 @@
     let a = true;
     let b = false;
     while a and b {  //~ ERROR `and` is not a logical operator
+                     //~| ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -52,6 +59,7 @@
     let a = true;
     let b = false;
     while a or b { //~ ERROR `or` is not a logical operator
+                   //~| ERROR `or` is not a logical operator
         println!("both");
     }
 }
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
index 528c62f..e8731cf23 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
@@ -7,7 +7,23 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `and` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15
+   |
+LL |     let _ = a and b;
+   |               ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:10:10
+   |
+LL |     if a and b {
+   |          ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:10:10
    |
 LL |     if a and b {
    |          ^^^ help: use `&&` to perform logical conjunction
@@ -15,7 +31,7 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:15
    |
 LL |     let _ = a or b;
    |               ^^ help: use `||` to perform logical disjunction
@@ -23,7 +39,23 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:15
+   |
+LL |     let _ = a or b;
+   |               ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:25:10
+   |
+LL |     if a or b {
+   |          ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:25:10
    |
 LL |     if a or b {
    |          ^^ help: use `||` to perform logical disjunction
@@ -31,7 +63,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `and` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:34:11
+   |
+LL |     if (a and b) {
+   |           ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:34:11
    |
 LL |     if (a and b) {
    |           ^^^ help: use `&&` to perform logical conjunction
@@ -39,7 +79,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:43:11
+   |
+LL |     if (a or b) {
+   |           ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:43:11
    |
 LL |     if (a or b) {
    |           ^^ help: use `||` to perform logical disjunction
@@ -47,7 +95,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `and` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:52:13
+   |
+LL |     while a and b {
+   |             ^^^ help: use `&&` to perform logical conjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:52:13
    |
 LL |     while a and b {
    |             ^^^ help: use `&&` to perform logical conjunction
@@ -55,7 +111,15 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error: `or` is not a logical operator
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:61:13
+   |
+LL |     while a or b {
+   |             ^^ help: use `||` to perform logical disjunction
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:61:13
    |
 LL |     while a or b {
    |             ^^ help: use `||` to perform logical disjunction
@@ -63,13 +127,13 @@
    = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:15:33
    |
 LL |     let _recovery_witness: () = 0;
    |                            --   ^ expected `()`, found integer
    |                            |
    |                            expected due to this
 
-error: aborting due to 9 previous errors
+error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dont-suggest-private-trait-method.rs b/src/test/ui/dont-suggest-private-trait-method.rs
index ef0904c..6e2b1ab 100644
--- a/src/test/ui/dont-suggest-private-trait-method.rs
+++ b/src/test/ui/dont-suggest-private-trait-method.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     T::new();
-    //~^ ERROR no function or associated item named `new` found for type `T` in the current scope
+    //~^ ERROR no function or associated item named `new` found
 }
diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr
index 5189ffa..fd7fdb4 100644
--- a/src/test/ui/dont-suggest-private-trait-method.stderr
+++ b/src/test/ui/dont-suggest-private-trait-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new` found for type `T` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `T` in the current scope
   --> $DIR/dont-suggest-private-trait-method.rs:4:8
    |
 LL | struct T;
diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs
index 91063ed..30a8960 100644
--- a/src/test/ui/drop/dynamic-drop-async.rs
+++ b/src/test/ui/drop/dynamic-drop-async.rs
@@ -7,7 +7,6 @@
 // edition:2018
 // ignore-wasm32-bare compiled with panic=abort by default
 
-#![feature(slice_patterns)]
 #![allow(unused)]
 
 use std::{
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index 0f0ec0b..b440620 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -1,11 +1,10 @@
 // run-pass
-#![allow(unused_assignments)]
-#![allow(unused_variables)]
-
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions)]
-#![feature(slice_patterns)]
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 
 use std::cell::{Cell, RefCell};
 use std::mem::ManuallyDrop;
diff --git a/src/test/ui/dst/dst-bad-assign-3.rs b/src/test/ui/dst/dst-bad-assign-3.rs
index e3b621b..d05b393 100644
--- a/src/test/ui/dst/dst-bad-assign-3.rs
+++ b/src/test/ui/dst/dst-bad-assign-3.rs
@@ -32,7 +32,7 @@
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.2 = Bar1 {f: 36};
     //~^ ERROR mismatched types
-    //~| expected trait `ToBar`, found struct `Bar1`
+    //~| expected trait object `dyn ToBar`, found struct `Bar1`
     //~| expected trait object `dyn ToBar`
     //~| found struct `Bar1`
     //~| ERROR the size for values of type
diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr
index dc03f38..0b6f9df 100644
--- a/src/test/ui/dst/dst-bad-assign-3.stderr
+++ b/src/test/ui/dst/dst-bad-assign-3.stderr
@@ -2,7 +2,7 @@
   --> $DIR/dst-bad-assign-3.rs:33:12
    |
 LL |     f5.2 = Bar1 {f: 36};
-   |            ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
+   |            ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
diff --git a/src/test/ui/dst/dst-bad-assign.rs b/src/test/ui/dst/dst-bad-assign.rs
index ed94242..496e01a 100644
--- a/src/test/ui/dst/dst-bad-assign.rs
+++ b/src/test/ui/dst/dst-bad-assign.rs
@@ -34,7 +34,7 @@
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.ptr = Bar1 {f: 36};
     //~^ ERROR mismatched types
-    //~| expected trait `ToBar`, found struct `Bar1`
+    //~| expected trait object `dyn ToBar`, found struct `Bar1`
     //~| expected trait object `dyn ToBar`
     //~| found struct `Bar1`
     //~| ERROR the size for values of type
diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr
index 8031f16..434c460 100644
--- a/src/test/ui/dst/dst-bad-assign.stderr
+++ b/src/test/ui/dst/dst-bad-assign.stderr
@@ -2,7 +2,7 @@
   --> $DIR/dst-bad-assign.rs:35:14
    |
 LL |     f5.ptr = Bar1 {f: 36};
-   |              ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
+   |              ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
diff --git a/src/test/ui/duplicate_entry_error.rs b/src/test/ui/duplicate_entry_error.rs
index 62df42b..b8d98a8 100644
--- a/src/test/ui/duplicate_entry_error.rs
+++ b/src/test/ui/duplicate_entry_error.rs
@@ -8,7 +8,7 @@
 
 #[lang = "panic_impl"]
 fn panic_impl(info: &PanicInfo) -> ! {
-//~^ ERROR: duplicate lang item found: `panic_impl`.
+//~^ ERROR: found duplicate lang item `panic_impl`
     loop {}
 }
 
diff --git a/src/test/ui/duplicate_entry_error.stderr b/src/test/ui/duplicate_entry_error.stderr
index 02be11d..46b137b 100644
--- a/src/test/ui/duplicate_entry_error.stderr
+++ b/src/test/ui/duplicate_entry_error.stderr
@@ -1,4 +1,4 @@
-error[E0152]: duplicate lang item found: `panic_impl`.
+error[E0152]: found duplicate lang item `panic_impl`
   --> $DIR/duplicate_entry_error.rs:10:1
    |
 LL | / fn panic_impl(info: &PanicInfo) -> ! {
@@ -7,7 +7,7 @@
 LL | | }
    | |_^
    |
-   = note: first defined in crate `std` (which `duplicate_entry_error` depends on).
+   = note: first defined in crate `std` (which `duplicate_entry_error` depends on)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/empty/empty-struct-braces-expr.rs b/src/test/ui/empty/empty-struct-braces-expr.rs
index 1a38d3d..f414427 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.rs
+++ b/src/test/ui/empty/empty-struct-braces-expr.rs
@@ -22,8 +22,8 @@
     let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
     let xe1 = XEmpty1();
     //~^ ERROR expected function, tuple struct or tuple variant, found struct `XEmpty1`
-    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for type
-    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for type
+    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for enum
+    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for enum
 
-    XE::Empty1 {}; //~ ERROR no variant `Empty1` in enum `empty_struct::XE`
+    XE::Empty1 {}; //~ ERROR no variant named `Empty1` found for enum `empty_struct::XE`
 }
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index f427c1b..9da3a5f 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -9,6 +9,11 @@
    |              |
    |              did you mean `Empty1 { /* fields */ }`?
    |              help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-expr.rs:16:14
@@ -21,6 +26,11 @@
    |              |
    |              did you mean `Empty1 { /* fields */ }`?
    |              help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
 error[E0423]: expected value, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:18:14
@@ -48,6 +58,11 @@
    |               |
    |               did you mean `XEmpty1 { /* fields */ }`?
    |               help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:23:15
@@ -57,8 +72,13 @@
    |               |
    |               did you mean `XEmpty1 { /* fields */ }`?
    |               help: a unit struct with a similar name exists: `XEmpty2`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |
+LL | pub struct XEmpty2;
+   | ------------------- similarly named unit struct `XEmpty2` defined here
 
-error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
@@ -67,7 +87,7 @@
    |                   variant or associated item not found in `empty_struct::XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
@@ -76,7 +96,7 @@
    |                   variant or associated item not found in `empty_struct::XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error: no variant `Empty1` in enum `empty_struct::XE`
+error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
   --> $DIR/empty-struct-braces-expr.rs:28:9
    |
 LL |     XE::Empty1 {};
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
index 9b5f311..0ff21c9 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -15,6 +15,11 @@
    |         |   |
    |         |   help: a unit variant with a similar name exists: `XEmpty4`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:7:5
+   |
+LL |     XEmpty4,
+   |     ------- similarly named unit variant `XEmpty4` defined here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
index 0b3c9ae..80c29db 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
@@ -9,6 +9,11 @@
    |         |
    |         did you mean `Empty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:18:9
@@ -18,6 +23,11 @@
    |         |
    |         did you mean `XEmpty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-pat-2.rs:21:9
@@ -30,6 +40,11 @@
    |         |
    |         did you mean `Empty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:24:9
@@ -39,6 +54,11 @@
    |         |
    |         did you mean `XEmpty1 { /* fields */ }`?
    |         help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
index 785396c..05439b3 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -15,6 +15,11 @@
    |         |   |
    |         |   help: a tuple variant with a similar name exists: `XEmpty5`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:25:9
@@ -33,6 +38,11 @@
    |         |   |
    |         |   help: a tuple variant with a similar name exists: `XEmpty5`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr
index cfbb468..9388ed2 100644
--- a/src/test/ui/empty/empty-struct-tuple-pat.stderr
+++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr
@@ -33,6 +33,11 @@
    |         |   |
    |         |   help: a unit variant with a similar name exists: `XEmpty4`
    |         did you mean `XE::XEmpty5( /* fields */ )`?
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:7:5
+   |
+LL |     XEmpty4,
+   |     ------- similarly named unit variant `XEmpty4` defined here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr
index fd41a6e..8ee14a3 100644
--- a/src/test/ui/empty/empty-struct-unit-pat.stderr
+++ b/src/test/ui/empty/empty-struct-unit-pat.stderr
@@ -3,24 +3,44 @@
    |
 LL |         Empty2() => ()
    |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
   --> $DIR/empty-struct-unit-pat.rs:24:9
    |
 LL |         XEmpty2() => ()
    |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2`
   --> $DIR/empty-struct-unit-pat.rs:28:9
    |
 LL |         Empty2(..) => ()
    |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2`
   --> $DIR/empty-struct-unit-pat.rs:32:9
    |
 LL |         XEmpty2(..) => ()
    |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:3:1
+   |
+LL | pub struct XEmpty6();
+   | --------------------- similarly named tuple struct `XEmpty6` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
   --> $DIR/empty-struct-unit-pat.rs:37:9
@@ -35,6 +55,11 @@
    |         ^^^^-------
    |             |
    |             help: a tuple variant with a similar name exists: `XEmpty5`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4`
   --> $DIR/empty-struct-unit-pat.rs:46:9
@@ -49,6 +74,11 @@
    |         ^^^^-------
    |             |
    |             help: a tuple variant with a similar name exists: `XEmpty5`
+   | 
+  ::: $DIR/auxiliary/empty-struct.rs:8:5
+   |
+LL |     XEmpty5(),
+   |     --------- similarly named tuple variant `XEmpty5` defined here
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/error-codes/E0030.rs b/src/test/ui/error-codes/E0030.rs
index 58d856b..a5d8f87 100644
--- a/src/test/ui/error-codes/E0030.rs
+++ b/src/test/ui/error-codes/E0030.rs
@@ -2,5 +2,6 @@
     match 5u32 {
         1000 ..= 5 => {}
         //~^ ERROR lower range bound must be less than or equal to upper
+        //~| ERROR lower range bound must be less than or equal to upper
     }
 }
diff --git a/src/test/ui/error-codes/E0030.stderr b/src/test/ui/error-codes/E0030.stderr
index db8161d..8a61140 100644
--- a/src/test/ui/error-codes/E0030.stderr
+++ b/src/test/ui/error-codes/E0030.stderr
@@ -4,6 +4,12 @@
 LL |         1000 ..= 5 => {}
    |         ^^^^ lower bound larger than upper bound
 
-error: aborting due to previous error
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/E0030.rs:3:9
+   |
+LL |         1000 ..= 5 => {}
+   |         ^^^^ lower bound larger than upper bound
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0030`.
diff --git a/src/test/ui/error-codes/E0106.rs b/src/test/ui/error-codes/E0106.rs
index d6537d1..cc34387 100644
--- a/src/test/ui/error-codes/E0106.rs
+++ b/src/test/ui/error-codes/E0106.rs
@@ -16,7 +16,7 @@
 struct Quux {
     baz: Baz,
     //~^ ERROR E0106
-    //~| expected lifetime parameter
+    //~| expected named lifetime parameter
     buzz: Buzz,
     //~^ ERROR E0106
     //~| expected 2 lifetime parameters
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
index cea9581..e01e0a6 100644
--- a/src/test/ui/error-codes/E0106.stderr
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -2,25 +2,49 @@
   --> $DIR/E0106.rs:2:8
    |
 LL |     x: &bool,
-   |        ^ expected lifetime parameter
+   |        ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Foo<'lifetime> {
+LL |     x: &'lifetime bool,
+   |
 
 error[E0106]: missing lifetime specifier
   --> $DIR/E0106.rs:7:7
    |
 LL |     B(&bool),
-   |       ^ expected lifetime parameter
+   |       ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | enum Bar<'lifetime> {
+LL |     A(u8),
+LL |     B(&'lifetime bool),
+   |
 
 error[E0106]: missing lifetime specifier
   --> $DIR/E0106.rs:10:14
    |
 LL | type MyStr = &str;
-   |              ^ expected lifetime parameter
+   |              ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | type MyStr<'lifetime> = &'lifetime str;
+   |           ^^^^^^^^^^^   ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/E0106.rs:17:10
    |
 LL |     baz: Baz,
-   |          ^^^ expected lifetime parameter
+   |          ^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Quux<'lifetime> {
+LL |     baz: Baz<'lifetime>,
+   |
 
 error[E0106]: missing lifetime specifiers
   --> $DIR/E0106.rs:20:11
diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr
index d4b59a1..c41a043 100644
--- a/src/test/ui/error-codes/E0152.stderr
+++ b/src/test/ui/error-codes/E0152.stderr
@@ -1,10 +1,10 @@
-error[E0152]: duplicate lang item found: `arc`.
+error[E0152]: found duplicate lang item `arc`
   --> $DIR/E0152.rs:4:1
    |
 LL | struct Foo;
    | ^^^^^^^^^^^
    |
-   = note: first defined in crate `alloc` (which `std` depends on).
+   = note: first defined in crate `alloc` (which `std` depends on)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0261.stderr b/src/test/ui/error-codes/E0261.stderr
index 3bf5e9d..0eab2dc 100644
--- a/src/test/ui/error-codes/E0261.stderr
+++ b/src/test/ui/error-codes/E0261.stderr
@@ -2,11 +2,15 @@
   --> $DIR/E0261.rs:1:12
    |
 LL | fn foo(x: &'a str) { }
-   |            ^^ undeclared lifetime
+   |       -    ^^ undeclared lifetime
+   |       |
+   |       help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/E0261.rs:5:9
    |
+LL | struct Foo {
+   |           - help: consider introducing lifetime `'a` here: `<'a>`
 LL |     x: &'a str,
    |         ^^ undeclared lifetime
 
diff --git a/src/test/ui/error-codes/E0452.rs b/src/test/ui/error-codes/E0452.rs
index 940b9f6..4e5a6c9 100644
--- a/src/test/ui/error-codes/E0452.rs
+++ b/src/test/ui/error-codes/E0452.rs
@@ -1,4 +1,8 @@
 #![allow(foo = "")] //~ ERROR E0452
-
+                    //~| ERROR E0452
+                    //~| ERROR E0452
+                    //~| ERROR E0452
+                    //~| ERROR E0452
+                    //~| ERROR E0452
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0452.stderr b/src/test/ui/error-codes/E0452.stderr
index 7f07416..30c11e3 100644
--- a/src/test/ui/error-codes/E0452.stderr
+++ b/src/test/ui/error-codes/E0452.stderr
@@ -4,6 +4,36 @@
 LL | #![allow(foo = "")]
    |          ^^^^^^^^ bad attribute argument
 
-error: aborting due to previous error
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/E0452.rs:1:10
+   |
+LL | #![allow(foo = "")]
+   |          ^^^^^^^^ bad attribute argument
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/error-codes/E0453.rs b/src/test/ui/error-codes/E0453.rs
index 46fa048..69155b0 100644
--- a/src/test/ui/error-codes/E0453.rs
+++ b/src/test/ui/error-codes/E0453.rs
@@ -2,5 +2,7 @@
 
 #[allow(non_snake_case)]
 //~^ ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
+//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
+//~| ERROR allow(non_snake_case) overruled by outer forbid(non_snake_case)
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0453.stderr b/src/test/ui/error-codes/E0453.stderr
index 03cc756..138e848 100644
--- a/src/test/ui/error-codes/E0453.stderr
+++ b/src/test/ui/error-codes/E0453.stderr
@@ -7,6 +7,24 @@
 LL | #[allow(non_snake_case)]
    |         ^^^^^^^^^^^^^^ overruled by previous forbid
 
-error: aborting due to previous error
+error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+  --> $DIR/E0453.rs:3:9
+   |
+LL | #![forbid(non_snake_case)]
+   |           -------------- `forbid` level set here
+LL | 
+LL | #[allow(non_snake_case)]
+   |         ^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(non_snake_case) overruled by outer forbid(non_snake_case)
+  --> $DIR/E0453.rs:3:9
+   |
+LL | #![forbid(non_snake_case)]
+   |           -------------- `forbid` level set here
+LL | 
+LL | #[allow(non_snake_case)]
+   |         ^^^^^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/error-codes/E0528.rs b/src/test/ui/error-codes/E0528.rs
index 17d03b14..0a337c9 100644
--- a/src/test/ui/error-codes/E0528.rs
+++ b/src/test/ui/error-codes/E0528.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     let r = &[1, 2];
     match r {
diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr
index 0f56609..21615f9 100644
--- a/src/test/ui/error-codes/E0528.stderr
+++ b/src/test/ui/error-codes/E0528.stderr
@@ -1,5 +1,5 @@
 error[E0528]: pattern requires at least 3 elements but array has 2
-  --> $DIR/E0528.rs:6:10
+  --> $DIR/E0528.rs:4:10
    |
 LL |         &[a, b, c, rest @ ..] => {
    |          ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
diff --git a/src/test/ui/error-codes/E0565.rs b/src/test/ui/error-codes/E0565.rs
index b09f5df..3bf4286 100644
--- a/src/test/ui/error-codes/E0565.rs
+++ b/src/test/ui/error-codes/E0565.rs
@@ -1,5 +1,6 @@
 // repr currently doesn't support literals
 #[repr("C")] //~ ERROR E0565
+             //~| ERROR E0565
 struct A {  }
 
 fn main() {  }
diff --git a/src/test/ui/error-codes/E0565.stderr b/src/test/ui/error-codes/E0565.stderr
index 6ed90c0..aa09515 100644
--- a/src/test/ui/error-codes/E0565.stderr
+++ b/src/test/ui/error-codes/E0565.stderr
@@ -4,6 +4,12 @@
 LL | #[repr("C")]
    |        ^^^
 
-error: aborting due to previous error
+error[E0565]: meta item in `repr` must be an identifier
+  --> $DIR/E0565.rs:2:8
+   |
+LL | #[repr("C")]
+   |        ^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/error-codes/E0586.stderr b/src/test/ui/error-codes/E0586.stderr
index d1e7e3f..0bbf9a6 100644
--- a/src/test/ui/error-codes/E0586.stderr
+++ b/src/test/ui/error-codes/E0586.stderr
@@ -1,10 +1,10 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/E0586.rs:3:22
+  --> $DIR/E0586.rs:3:19
    |
 LL |     let x = &tmp[1..=];
-   |                      ^
+   |                   ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr
index 89bfccf..a78a003 100644
--- a/src/test/ui/error-codes/E0599.stderr
+++ b/src/test/ui/error-codes/E0599.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope
+error[E0599]: no associated item named `NotEvenReal` found for struct `Foo` in the current scope
   --> $DIR/E0599.rs:4:20
    |
 LL | struct Foo;
diff --git a/src/test/ui/error-codes/E0602.stderr b/src/test/ui/error-codes/E0602.stderr
index 8636004..70137cb 100644
--- a/src/test/ui/error-codes/E0602.stderr
+++ b/src/test/ui/error-codes/E0602.stderr
@@ -2,6 +2,14 @@
    |
    = note: requested on the command line with `-D bogus`
 
-error: aborting due to previous error
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/error-codes/E0603.stderr b/src/test/ui/error-codes/E0603.stderr
index 444005e..724d049 100644
--- a/src/test/ui/error-codes/E0603.stderr
+++ b/src/test/ui/error-codes/E0603.stderr
@@ -2,7 +2,13 @@
   --> $DIR/E0603.rs:6:17
    |
 LL |     SomeModule::PRIVATE;
-   |                 ^^^^^^^
+   |                 ^^^^^^^ this constant is private
+   |
+note: the constant `PRIVATE` is defined here
+  --> $DIR/E0603.rs:2:5
+   |
+LL |     const PRIVATE: u32 = 0x_a_bad_1dea_u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0658.stderr b/src/test/ui/error-codes/E0658.stderr
index 071dbcc..1cb81c8 100644
--- a/src/test/ui/error-codes/E0658.stderr
+++ b/src/test/ui/error-codes/E0658.stderr
@@ -6,7 +6,7 @@
 LL | | }
    | |_^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/35118
+   = note: for more information, see https://github.com/rust-lang/rust/issues/56071
    = help: add `#![feature(repr128)]` to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0746.fixed b/src/test/ui/error-codes/E0746.fixed
new file mode 100644
index 0000000..ca8319a
--- /dev/null
+++ b/src/test/ui/error-codes/E0746.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+#![allow(dead_code)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn foo() -> impl Trait { Struct }
+//~^ ERROR E0746
+
+fn bar() -> impl Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0746.rs b/src/test/ui/error-codes/E0746.rs
new file mode 100644
index 0000000..bf5ba8f
--- /dev/null
+++ b/src/test/ui/error-codes/E0746.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+#![allow(dead_code)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn foo() -> dyn Trait { Struct }
+//~^ ERROR E0746
+
+fn bar() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0746.stderr b/src/test/ui/error-codes/E0746.stderr
new file mode 100644
index 0000000..e7a8fd3
--- /dev/null
+++ b/src/test/ui/error-codes/E0746.stderr
@@ -0,0 +1,27 @@
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/E0746.rs:8:13
+   |
+LL | fn foo() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn foo() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/E0746.rs:11:13
+   |
+LL | fn bar() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
+   |
+LL | fn bar() -> impl Trait {
+   |             ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0746`.
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 73571a3..9b69b37 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -8,7 +8,13 @@
   --> $DIR/error-festival.rs:22:10
    |
 LL |     foo::FOO;
-   |          ^^^
+   |          ^^^ this constant is private
+   |
+note: the constant `FOO` is defined here
+  --> $DIR/error-festival.rs:7:5
+   |
+LL |     const FOO: u32 = 0;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0368]: binary assignment operation `+=` cannot be applied to type `&str`
   --> $DIR/error-festival.rs:12:5
@@ -20,7 +26,7 @@
    |
    = note: an implementation of `std::ops::AddAssign` might be missing for `&str`
 
-error[E0599]: no method named `z` found for type `&str` in the current scope
+error[E0599]: no method named `z` found for reference `&str` in the current scope
   --> $DIR/error-festival.rs:16:7
    |
 LL |     x.z();
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
deleted file mode 100644
index d97b693..0000000
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(exclusive_range_pattern)]
-
-fn main() {
-    match [5..4, 99..105, 43..44] {
-        [_, 99.., _] => {},
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR mismatched types
-        _ => {},
-    }
-}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
deleted file mode 100644
index 76ae724..0000000
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: `X..` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
-   |
-LL |         [_, 99.., _] => {},
-   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
-
-error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
-   |
-LL |     match [5..4, 99..105, 43..44] {
-   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
-LL |         [_, 99.., _] => {},
-   |             ^^ expected struct `std::ops::Range`, found integer
-   |
-   = note: expected struct `std::ops::Range<{integer}>`
-                found type `{integer}`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
deleted file mode 100644
index 09f459c..0000000
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(exclusive_range_pattern)]
-
-fn main() {
-    match [5..4, 99..105, 43..44] {
-        [_, 99..] => {},
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR pattern requires 2 elements but array has 3
-        //~| ERROR mismatched types
-        _ => {},
-    }
-}
diff --git a/src/test/ui/export-import.stderr b/src/test/ui/export-import.stderr
index e02952e..8160775 100644
--- a/src/test/ui/export-import.stderr
+++ b/src/test/ui/export-import.stderr
@@ -2,7 +2,13 @@
   --> $DIR/export-import.rs:1:8
    |
 LL | use m::unexported;
-   |        ^^^^^^^^^^
+   |        ^^^^^^^^^^ this function is private
+   |
+note: the function `unexported` is defined here
+  --> $DIR/export-import.rs:7:5
+   |
+LL |     fn unexported() { }
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/export-tag-variant.stderr b/src/test/ui/export-tag-variant.stderr
index b5a2c12..f4537a2 100644
--- a/src/test/ui/export-tag-variant.stderr
+++ b/src/test/ui/export-tag-variant.stderr
@@ -2,7 +2,13 @@
   --> $DIR/export-tag-variant.rs:7:26
    |
 LL | fn main() { let z = foo::Y::Y1; }
-   |                          ^
+   |                          ^ this enum is private
+   |
+note: the enum `Y` is defined here
+  --> $DIR/export-tag-variant.rs:4:5
+   |
+LL |     enum Y { Y1 }
+   |     ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/export.stderr b/src/test/ui/export.stderr
index a3668a5..107f531 100644
--- a/src/test/ui/export.stderr
+++ b/src/test/ui/export.stderr
@@ -26,7 +26,13 @@
   --> $DIR/export.rs:10:18
    |
 LL | fn main() { foo::z(10); }
-   |                  ^
+   |                  ^ this function is private
+   |
+note: the function `z` is defined here
+  --> $DIR/export.rs:5:5
+   |
+LL |     fn z(y: isize) { log(debug, y); }
+   |     ^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/extern/extern-crate-visibility.rs b/src/test/ui/extern/extern-crate-visibility.rs
index e0a5cd5..cda1227 100644
--- a/src/test/ui/extern/extern-crate-visibility.rs
+++ b/src/test/ui/extern/extern-crate-visibility.rs
@@ -3,10 +3,10 @@
 }
 
 // Check that private crates can be used from outside their modules, albeit with warnings
-use foo::core::cell; //~ ERROR crate `core` is private
+use foo::core::cell; //~ ERROR crate import `core` is private
 
 fn f() {
-    foo::core::cell::Cell::new(0); //~ ERROR crate `core` is private
+    foo::core::cell::Cell::new(0); //~ ERROR crate import `core` is private
 
     use foo::*;
     mod core {} // Check that private crates are not glob imported
diff --git a/src/test/ui/extern/extern-crate-visibility.stderr b/src/test/ui/extern/extern-crate-visibility.stderr
index 38c791a..d0c073d 100644
--- a/src/test/ui/extern/extern-crate-visibility.stderr
+++ b/src/test/ui/extern/extern-crate-visibility.stderr
@@ -1,14 +1,26 @@
-error[E0603]: crate `core` is private
+error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:6:10
    |
 LL | use foo::core::cell;
-   |          ^^^^
+   |          ^^^^ this crate import is private
+   |
+note: the crate import `core` is defined here
+  --> $DIR/extern-crate-visibility.rs:2:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^
 
-error[E0603]: crate `core` is private
+error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:9:10
    |
 LL |     foo::core::cell::Cell::new(0);
-   |          ^^^^
+   |          ^^^^ this crate import is private
+   |
+note: the crate import `core` is defined here
+  --> $DIR/extern-crate-visibility.rs:2:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr
index 2e258d6..32b45ee 100644
--- a/src/test/ui/extern/extern-types-distinct-types.stderr
+++ b/src/test/ui/extern/extern-types-distinct-types.stderr
@@ -1,6 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/extern-types-distinct-types.rs:9:5
    |
+LL |     type A;
+   |     ------- the found foreign type
+LL |     type B;
+   |     ------- the expected foreign type
+...
 LL |     r
    |     ^ expected extern type `B`, found extern type `A`
    |
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 0d804f0..f702b10 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
@@ -12,7 +12,7 @@
 // the change when it happens.
 //
 // At the time of authoring, the attributes here are listed in the
-// order that they occur in libsyntax/feature_gate.rs.
+// order that they occur in `librustc_feature`.
 //
 // Any builtin attributes that:
 //
@@ -464,10 +464,10 @@
 
 // Cannot feed "2700" to `#[macro_escape]` without signaling an error.
 #[macro_escape]
-//~^ WARN macro_escape is a deprecated synonym for macro_use
+//~^ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
 mod macro_escape {
     mod inner { #![macro_escape] }
-    //~^ WARN macro_escape is a deprecated synonym for macro_use
+    //~^ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
 
     #[macro_escape] fn f() { }
     //~^ WARN unused attribute
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 9ce90d8..da7d8f9 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
@@ -172,19 +172,19 @@
 LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
-warning: macro_escape is a deprecated synonym for macro_use
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
 
-warning: macro_escape is a deprecated synonym for macro_use
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
    |
-   = help: consider an outer attribute, `#[macro_use]` mod ...
+   = help: try an outer attribute: `#[macro_use]`
 
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:17
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
index 5f276f6..3276309 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
@@ -3,14 +3,17 @@
 mod derive {
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
+    //~| ERROR cannot find derive macro `x3300` in this scope
     union U { f: i32 }
 
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
+    //~| ERROR cannot find derive macro `x3300` in this scope
     enum E { }
 
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
+    //~| ERROR cannot find derive macro `x3300` in this scope
     struct S;
 }
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
index f14591c..ab16591 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
@@ -1,11 +1,23 @@
 error: cannot find derive macro `x3300` in this scope
-  --> $DIR/issue-43106-gating-of-derive-2.rs:12:14
+  --> $DIR/issue-43106-gating-of-derive-2.rs:14:14
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
 
 error: cannot find derive macro `x3300` in this scope
-  --> $DIR/issue-43106-gating-of-derive-2.rs:8:14
+  --> $DIR/issue-43106-gating-of-derive-2.rs:14:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:9:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:9:14
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
@@ -16,5 +28,11 @@
 LL |     #[derive(x3300)]
    |              ^^^^^
 
-error: aborting due to 3 previous errors
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:4:14
+   |
+LL |     #[derive(x3300)]
+   |              ^^^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
index 75a3d91..de00bc4 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
@@ -6,6 +6,6 @@
 // check-pass
 
 #![macro_escape]
-//~^ WARN macro_escape is a deprecated synonym for macro_use
+//~^ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
 
 fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
index 8575c16..402dc4e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
@@ -1,8 +1,8 @@
-warning: macro_escape is a deprecated synonym for macro_use
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/issue-43106-gating-of-macro_escape.rs:8:1
    |
 LL | #![macro_escape]
    | ^^^^^^^^^^^^^^^^
    |
-   = help: consider an outer attribute, `#[macro_use]` mod ...
+   = help: try an outer attribute: `#[macro_use]`
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
index 4ced941..6a7ef79 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
@@ -4,13 +4,13 @@
 // get that warning; see issue-43106-gating-of-builtin-attrs.rs
 
 #![macro_use(my_macro)]
-//~^ ERROR arguments to macro_use are not allowed here
+//~^ ERROR arguments to `macro_use` are not allowed here
 
 #[macro_use(my_macro)]
-//~^ ERROR arguments to macro_use are not allowed here
+//~^ ERROR arguments to `macro_use` are not allowed here
 mod macro_escape {
     mod inner { #![macro_use(my_macro)] }
-    //~^ ERROR arguments to macro_use are not allowed here
+    //~^ ERROR arguments to `macro_use` are not allowed here
 
     #[macro_use = "2700"] struct S;
     //~^ ERROR malformed `macro_use` attribute
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
index 3181d62..52a682e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
@@ -1,16 +1,16 @@
-error: arguments to macro_use are not allowed here
+error: arguments to `macro_use` are not allowed here
   --> $DIR/issue-43106-gating-of-macro_use.rs:6:1
    |
 LL | #![macro_use(my_macro)]
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: arguments to macro_use are not allowed here
+error: arguments to `macro_use` are not allowed here
   --> $DIR/issue-43106-gating-of-macro_use.rs:9:1
    |
 LL | #[macro_use(my_macro)]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
-error: arguments to macro_use are not allowed here
+error: arguments to `macro_use` are not allowed here
   --> $DIR/issue-43106-gating-of-macro_use.rs:12:17
    |
 LL |     mod inner { #![macro_use(my_macro)] }
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
index 60873f9..a01d855 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
@@ -18,6 +18,7 @@
 
     #[rustc_deprecated()] struct S;
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR stability attributes may not be used outside of the standard library
 
     #[rustc_deprecated()] type T = S;
     //~^ ERROR stability attributes may not be used outside of the standard library
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
index 8c6c26f..3c4dcfe 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
@@ -29,17 +29,23 @@
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:22:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:19:5
+   |
+LL |     #[rustc_deprecated()] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:23:5
    |
 LL |     #[rustc_deprecated()] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:25:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5
    |
 LL |     #[rustc_deprecated()] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
index e3ac274..73ff965 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
@@ -18,6 +18,7 @@
 
     #[stable()] struct S;
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR stability attributes may not be used outside of the standard library
 
     #[stable()] type T = S;
     //~^ ERROR stability attributes may not be used outside of the standard library
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
index 09dabd2..2573db1 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
@@ -29,17 +29,23 @@
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:22:5
+  --> $DIR/issue-43106-gating-of-stable.rs:19:5
+   |
+LL |     #[stable()] struct S;
+   |     ^^^^^^^^^^^
+
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:23:5
    |
 LL |     #[stable()] type T = S;
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:25:5
+  --> $DIR/issue-43106-gating-of-stable.rs:26:5
    |
 LL |     #[stable()] impl S { }
    |     ^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
index 8d519c3..d8339b0 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
@@ -18,6 +18,7 @@
 
     #[unstable()] struct S;
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR stability attributes may not be used outside of the standard library
 
     #[unstable()] type T = S;
     //~^ ERROR stability attributes may not be used outside of the standard library
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
index 49da2c5..500675e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
@@ -29,17 +29,23 @@
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:22:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:19:5
+   |
+LL |     #[unstable()] struct S;
+   |     ^^^^^^^^^^^^^
+
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:23:5
    |
 LL |     #[unstable()] type T = S;
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:25:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:26:5
    |
 LL |     #[unstable()] impl S { }
    |     ^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
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 9d68d3e..4e6e293 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,3 @@
 #[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental
+                          //~| 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 683c0ad..0534018 100644
--- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
@@ -7,6 +7,15 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/44732
    = help: add `#![feature(external_doc)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: `#[doc(include)]` is experimental
+  --> $DIR/feature-gate-external_doc.rs:1:1
+   |
+LL | #[doc(include="asdf.md")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44732
+   = help: add `#![feature(external_doc)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
index 5c64bf6..bbf3ea8 100644
--- a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
+++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
@@ -2,103 +2,207 @@
   --> $DIR/feature-gate-in_band_lifetimes.rs:3:12
    |
 LL | fn foo(x: &'x u8) -> &'x u8 { x }
-   |            ^^ undeclared lifetime
+   |       -    ^^ undeclared lifetime
+   |       |
+   |       help: consider introducing lifetime `'x` here: `<'x>`
 
 error[E0261]: use of undeclared lifetime name `'x`
   --> $DIR/feature-gate-in_band_lifetimes.rs:3:23
    |
 LL | fn foo(x: &'x u8) -> &'x u8 { x }
-   |                       ^^ undeclared lifetime
+   |       -               ^^ undeclared lifetime
+   |       |
+   |       help: consider introducing lifetime `'x` here: `<'x>`
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:15:12
    |
 LL | impl<'a> X<'b> {
-   |            ^^ undeclared lifetime
+   |      -     ^^ undeclared lifetime
+   |      |
+   |      help: consider introducing lifetime `'b` here: `'b,`
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:17:27
    |
 LL |     fn inner_2(&self) -> &'b u8 {
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> X<'b> {
+   |      ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn inner_2<'b>(&self) -> &'b u8 {
+   |               ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:23:8
    |
 LL | impl X<'b> {
-   |        ^^ undeclared lifetime
+   |     -  ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'b` here: `<'b>`
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:25:27
    |
 LL |     fn inner_3(&self) -> &'b u8 {
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> X<'b> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn inner_3<'b>(&self) -> &'b u8 {
+   |               ^^^^
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/feature-gate-in_band_lifetimes.rs:33:9
    |
 LL | impl Y<&'a u8> {
-   |         ^^ undeclared lifetime
+   |     -   ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/feature-gate-in_band_lifetimes.rs:35:25
    |
 LL |     fn inner(&self) -> &'a u8 {
    |                         ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn inner<'a>(&self) -> &'a u8 {
+   |             ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:43:27
    |
 LL |     fn any_lifetime() -> &'b u8;
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait MyTrait<'b, 'a> {
+   |               ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn any_lifetime<'b>() -> &'b u8;
+   |                    ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:45:27
    |
 LL |     fn borrowed_lifetime(&'b self) -> &'b u8;
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait MyTrait<'b, 'a> {
+   |               ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8;
+   |                         ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:45:40
    |
 LL |     fn borrowed_lifetime(&'b self) -> &'b u8;
    |                                        ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait MyTrait<'b, 'a> {
+   |               ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8;
+   |                         ^^^^
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/feature-gate-in_band_lifetimes.rs:50:14
    |
 LL | impl MyTrait<'a> for Y<&'a u8> {
-   |              ^^ undeclared lifetime
+   |     -        ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/feature-gate-in_band_lifetimes.rs:50:25
    |
 LL | impl MyTrait<'a> for Y<&'a u8> {
-   |                         ^^ undeclared lifetime
+   |     -                   ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/feature-gate-in_band_lifetimes.rs:53:31
    |
 LL |     fn my_lifetime(&self) -> &'a u8 { self.0 }
    |                               ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn my_lifetime<'a>(&self) -> &'a u8 { self.0 }
+   |                   ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
    |
 LL |     fn any_lifetime() -> &'b u8 { &0 }
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn any_lifetime<'b>() -> &'b u8 { &0 }
+   |                    ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:57:27
    |
 LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
+   |                         ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/feature-gate-in_band_lifetimes.rs:57:40
    |
 LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
    |                                        ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
+   |                         ^^^^
 
 error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
index 1a7b9c9..b124e9b 100644
--- a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs
@@ -1,4 +1,6 @@
 #![warn(nonstandard_style, reason = "the standard should be respected")]
 //~^ ERROR lint reasons are experimental
+//~| ERROR lint reasons are experimental
+//~| ERROR lint reasons are experimental
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
index 390a1bf..08ba9d0 100644
--- a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
@@ -7,6 +7,24 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/54503
    = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: lint reasons are experimental
+  --> $DIR/feature-gate-lint-reasons.rs:1:28
+   |
+LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54503
+   = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
+
+error[E0658]: lint reasons are experimental
+  --> $DIR/feature-gate-lint-reasons.rs:1:28
+   |
+LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54503
+   = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-never_type.stderr b/src/test/ui/feature-gates/feature-gate-never_type.stderr
index d86ab99..2166157 100644
--- a/src/test/ui/feature-gates/feature-gate-never_type.stderr
+++ b/src/test/ui/feature-gates/feature-gate-never_type.stderr
@@ -1,4 +1,4 @@
-error[E0658]: The `!` type is experimental
+error[E0658]: the `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:7:17
    |
 LL | type Ma = (u32, !, i32);
@@ -7,7 +7,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add `#![feature(never_type)]` to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental
+error[E0658]: the `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:8:20
    |
 LL | type Meeshka = Vec<!>;
@@ -16,7 +16,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add `#![feature(never_type)]` to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental
+error[E0658]: the `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:9:24
    |
 LL | type Mow = &'static fn(!) -> !;
@@ -25,7 +25,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add `#![feature(never_type)]` to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental
+error[E0658]: the `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:10:27
    |
 LL | type Skwoz = &'static mut !;
@@ -34,7 +34,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add `#![feature(never_type)]` to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental
+error[E0658]: the `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:13:16
    |
 LL |     type Wub = !;
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.rs b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
index 9d28f43..1e4a404f 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.rs
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.rs
@@ -1,7 +1,7 @@
 #[repr(simd)] //~ error: SIMD types are experimental
 struct Foo(u64, u64);
 
-#[repr(C)] //~ warn: conflicting representation hints
+#[repr(C)] //~ ERROR conflicting representation hints
 #[repr(simd)] //~ error: SIMD types are experimental
 struct Bar(u64, u64);
 
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
index 02c8400..37a7bd0 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -16,7 +16,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add `#![feature(repr_simd)]` to the crate attributes to enable
 
-warning[E0566]: conflicting representation hints
+error[E0566]: conflicting representation hints
   --> $DIR/feature-gate-repr-simd.rs:4:8
    |
 LL | #[repr(C)]
@@ -24,7 +24,7 @@
 LL | #[repr(simd)]
    |        ^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0566, E0658.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/feature-gates/feature-gate-repr128.stderr b/src/test/ui/feature-gates/feature-gate-repr128.stderr
index 2139a5d..e108d74 100644
--- a/src/test/ui/feature-gates/feature-gate-repr128.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr128.stderr
@@ -6,7 +6,7 @@
 LL | | }
    | |_^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/35118
+   = note: for more information, see https://github.com/rust-lang/rust/issues/56071
    = help: add `#![feature(repr128)]` to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
deleted file mode 100644
index 3b972c1..0000000
--- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
deleted file mode 100644
index b13ec21..0000000
--- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
-  --> $DIR/feature-gate-sanitizer-runtime.rs:1:1
-   |
-LL | #![sanitizer_runtime]
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(sanitizer_runtime)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
deleted file mode 100644
index f2a1b13..0000000
--- a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate
-
-fn main() {
-    let x = [1, 2, 3, 4, 5];
-    match x {
-        [1, 2, ..] => {} //~ ERROR subslice patterns are unstable
-        [1, .., 5] => {} //~ ERROR subslice patterns are unstable
-        [.., 4, 5] => {} //~ ERROR subslice patterns are unstable
-    }
-
-    let x = [ 1, 2, 3, 4, 5 ];
-    match x {
-        [ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable
-        [ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable
-        [ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable
-    }
-}
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
deleted file mode 100644
index d4946a4..0000000
--- a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
+++ /dev/null
@@ -1,57 +0,0 @@
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:6:16
-   |
-LL |         [1, 2, ..] => {}
-   |                ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:7:13
-   |
-LL |         [1, .., 5] => {}
-   |             ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:8:10
-   |
-LL |         [.., 4, 5] => {}
-   |          ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:13:11
-   |
-LL |         [ xs @ .., 4, 5 ] => {}
-   |           ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:14:14
-   |
-LL |         [ 1, xs @ .., 5 ] => {}
-   |              ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:15:17
-   |
-LL |         [ 1, 2, xs @ .. ] => {}
-   |                 ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/future-incompatible-lint-group.stderr b/src/test/ui/future-incompatible-lint-group.stderr
index 24e3a07..1d958e5 100644
--- a/src/test/ui/future-incompatible-lint-group.stderr
+++ b/src/test/ui/future-incompatible-lint-group.stderr
@@ -2,7 +2,7 @@
   --> $DIR/future-incompatible-lint-group.rs:4:10
    |
 LL |     fn f(u8) {}
-   |          ^^ help: Try naming the parameter or explicitly ignoring it: `_: u8`
+   |          ^^ help: try naming the parameter or explicitly ignoring it: `_: u8`
    |
 note: lint level defined here
   --> $DIR/future-incompatible-lint-group.rs:1:9
diff --git a/src/test/ui/generator/auto-trait-regions.nll.stderr b/src/test/ui/generator/auto-trait-regions.nll.stderr
index 4c157a0..bf87aea 100644
--- a/src/test/ui/generator/auto-trait-regions.nll.stderr
+++ b/src/test/ui/generator/auto-trait-regions.nll.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/auto-trait-regions.rs:44:24
+  --> $DIR/auto-trait-regions.rs:45:24
    |
 LL |         let a = A(&mut true, &mut true, No);
    |                        ^^^^                - temporary value is freed at the end of this statement
@@ -12,7 +12,7 @@
    = note: consider using a `let` binding to create a longer lived value
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/auto-trait-regions.rs:44:35
+  --> $DIR/auto-trait-regions.rs:45:35
    |
 LL |         let a = A(&mut true, &mut true, No);
    |                                   ^^^^     - temporary value is freed at the end of this statement
@@ -31,7 +31,7 @@
    |     ^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/auto-trait-regions.rs:48:5
+  --> $DIR/auto-trait-regions.rs:49:5
    |
 LL |     assert_foo(gen);
    |     ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs
index 46d7289..dbd8965 100644
--- a/src/test/ui/generator/auto-trait-regions.rs
+++ b/src/test/ui/generator/auto-trait-regions.rs
@@ -29,6 +29,7 @@
     };
     assert_foo(gen);
     //~^ ERROR implementation of `Foo` is not general enough
+    //~| ERROR implementation of `Foo` is not general enough
 
     // Allow impls which matches any lifetime
     let x = &OnlyFooIfRef(No);
@@ -47,4 +48,5 @@
     };
     assert_foo(gen);
     //~^ ERROR not general enough
+    //~| ERROR not general enough
 }
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
index dab4d34..29a3907 100644
--- a/src/test/ui/generator/auto-trait-regions.stderr
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -11,7 +11,19 @@
    = 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
+  --> $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`
+
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:49:5
    |
 LL | auto trait Foo {}
    | ----------------- trait `Foo` defined here
@@ -22,5 +34,17 @@
    = 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
+error: implementation of `Foo` is not general enough
+  --> $DIR/auto-trait-regions.rs:49: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`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index 0ac1d18..18d9012 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -20,7 +20,7 @@
 LL |     assert_sync(|| {
    |     ^^^^^^^^^^^ future returned by `main` is not `Sync`
    |
-   = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+   = 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: future is not `Sync` as this value is used across an yield
   --> $DIR/not-send-sync.rs:12:9
    |
diff --git a/src/test/ui/generator/static-mut-reference-across-yield.rs b/src/test/ui/generator/static-mut-reference-across-yield.rs
new file mode 100644
index 0000000..2926bba
--- /dev/null
+++ b/src/test/ui/generator/static-mut-reference-across-yield.rs
@@ -0,0 +1,29 @@
+// build-pass
+#![feature(generators)]
+
+static mut A: [i32; 5] = [1, 2, 3, 4, 5];
+
+fn is_send_sync<T: Send + Sync>(_: T) {}
+
+fn main() {
+    unsafe {
+        let gen_index = static || {
+            let u = A[{
+                yield;
+                1
+            }];
+        };
+        let gen_match = static || match A {
+            i if {
+                yield;
+                true
+            } =>
+            {
+                ()
+            }
+            _ => (),
+        };
+        is_send_sync(gen_index);
+        is_send_sync(gen_match);
+    }
+}
diff --git a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
index 81137e8..fc2ce1c 100644
--- a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
+++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
@@ -3,12 +3,30 @@
    |
 LL |         + Deref<Target = Self::Item<'b>>;
    |                                     ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait Iterable<'b> {
+   |               ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>>
+   |               ^^^
 
 error[E0261]: use of undeclared lifetime name `'undeclared`
   --> $DIR/generic_associated_type_undeclared_lifetimes.rs:12:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
    |                                         ^^^^^^^^^^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'undeclared` here
+   |
+LL | trait Iterable<'undeclared> {
+   |               ^^^^^^^^^^^^^
+help: consider introducing lifetime `'undeclared` here
+   |
+LL |     fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>;
+   |             ^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index 0179900..ca2350f 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -38,7 +38,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `Fooy<T>`
-   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl typebut not on the corresponding associated trait type
+   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl type but not on the corresponding associated trait type
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
new file mode 100644
index 0000000..3f4c178
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
@@ -0,0 +1,10 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [_, 99.., _] => {},
+        //~^ ERROR mismatched types
+        _ => {},
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
new file mode 100644
index 0000000..a6f8563
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
+LL |         [_, 99.., _] => {},
+   |             ^^ expected struct `std::ops::Range`, found integer
+   |
+   = note: expected struct `std::ops::Range<{integer}>`
+                found type `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
new file mode 100644
index 0000000..dedc854
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
@@ -0,0 +1,11 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    match [5..4, 99..105, 43..44] {
+        [_, 99..] => {},
+        //~^ ERROR pattern requires 2 elements but array has 3
+        //~| ERROR mismatched types
+        _ => {},
+    }
+}
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
similarity index 62%
rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 5c96f80..4e0102c 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -1,17 +1,11 @@
-error: `X..` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
-   |
-LL |         [_, 99..] => {},
-   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
-
 error[E0527]: pattern requires 2 elements but array has 3
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:9
    |
 LL |         [_, 99..] => {},
    |         ^^^^^^^^^ expected 3 elements
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -21,7 +15,7 @@
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0308, E0527.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
similarity index 69%
rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
index 1557f59..6a9b562 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
@@ -1,10 +1,10 @@
+#![feature(half_open_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
 fn main() {
     match [5..4, 99..105, 43..44] {
         [..9, 99..100, _] => {},
-        //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR mismatched types
+        //~^ ERROR mismatched types
         //~| ERROR mismatched types
         //~| ERROR mismatched types
         _ => {},
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
similarity index 75%
rename from src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
rename to src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index 17e1032..665eef2 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -1,11 +1,5 @@
-error: `..X` range patterns are not supported
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
-   |
-LL |         [..9, 99..100, _] => {},
-   |          ^^^ help: try using the minimum value for the type: `MIN..9`
-
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -16,7 +10,7 @@
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -29,7 +23,7 @@
                 found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -41,6 +35,6 @@
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
new file mode 100644
index 0000000..1733012
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
@@ -0,0 +1,22 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn foo() {
+    if let ..=5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let ...5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR range-to patterns with `...` are not allowed
+    if let ..5 = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let 5.. = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    if let 5..= = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR inclusive range with no end
+    if let 5... = 0 {}
+    //~^ ERROR half-open range patterns are unstable
+    //~| ERROR inclusive range with no end
+}
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
new file mode 100644
index 0000000..99db339
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
@@ -0,0 +1,80 @@
+error: range-to patterns with `...` are not allowed
+  --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
+   |
+LL |     if let ...5 = 0 {}
+   |            ^^^ help: use `..=` instead
+
+error[E0586]: inclusive range with no end
+  --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
+   |
+LL |     if let 5..= = 0 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/feature-gate-half-open-range-patterns.rs:19:13
+   |
+LL |     if let 5... = 0 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:7:12
+   |
+LL |     if let ..=5 = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
+   |
+LL |     if let ...5 = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:12:12
+   |
+LL |     if let ..5 = 0 {}
+   |            ^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:14:12
+   |
+LL |     if let 5.. = 0 {}
+   |            ^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:16:12
+   |
+LL |     if let 5..= = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: half-open range patterns are unstable
+  --> $DIR/feature-gate-half-open-range-patterns.rs:19:12
+   |
+LL |     if let 5... = 0 {}
+   |            ^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67264
+   = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0586, E0658.
+For more information about an error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
new file mode 100644
index 0000000..7cddf5f
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
@@ -0,0 +1,8 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let "a".. = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let .."a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let ..="a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
new file mode 100644
index 0000000..68ca363
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
@@ -0,0 +1,21 @@
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:5:9
+   |
+LL |     let "a".. = "a";
+   |         ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:6:11
+   |
+LL |     let .."a" = "a";
+   |           ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/half-open-range-pats-bad-types.rs:7:12
+   |
+LL |     let ..="a" = "a";
+   |            ^^^ this is of type `&'static str` but it should be `char` or numeric
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
new file mode 100644
index 0000000..b135891
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
@@ -0,0 +1,168 @@
+// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+fn main() {}
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn floats() {
+    m!(0f32, core::f32::NEG_INFINITY..); //~ ERROR non-exhaustive patterns: `_` not covered
+    m!(0f32, ..core::f32::INFINITY); //~ ERROR non-exhaustive patterns: `_` not covered
+}
+
+fn khar() {
+    const ALMOST_MAX: char = '\u{10fffe}';
+    const ALMOST_MIN: char = '\u{1}';
+    const VAL: char = 'a';
+    const VAL_1: char = 'b';
+    const VAL_2: char = 'c';
+    m!('a', ..core::char::MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+    m!('a', ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+    m!('a', ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+    m!('a', ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+}
+
+mod unsigned {
+    fn u8() {
+        const ALMOST_MAX: u8 = core::u8::MAX - 1;
+        const ALMOST_MIN: u8 = core::u8::MIN + 1;
+        const VAL: u8 = 42;
+        const VAL_1: u8 = VAL + 1;
+        const VAL_2: u8 = VAL + 2;
+        m!(0, ..core::u8::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u16() {
+        const ALMOST_MAX: u16 = core::u16::MAX - 1;
+        const ALMOST_MIN: u16 = core::u16::MIN + 1;
+        const VAL: u16 = 42;
+        const VAL_1: u16 = VAL + 1;
+        const VAL_2: u16 = VAL + 2;
+        m!(0, ..core::u16::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u32() {
+        const ALMOST_MAX: u32 = core::u32::MAX - 1;
+        const ALMOST_MIN: u32 = core::u32::MIN + 1;
+        const VAL: u32 = 42;
+        const VAL_1: u32 = VAL + 1;
+        const VAL_2: u32 = VAL + 2;
+        m!(0, ..core::u32::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u64() {
+        const ALMOST_MAX: u64 = core::u64::MAX - 1;
+        const ALMOST_MIN: u64 = core::u64::MIN + 1;
+        const VAL: u64 = 42;
+        const VAL_1: u64 = VAL + 1;
+        const VAL_2: u64 = VAL + 2;
+        m!(0, ..core::u64::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn u128() {
+        const ALMOST_MAX: u128 = core::u128::MAX - 1;
+        const ALMOST_MIN: u128 = core::u128::MIN + 1;
+        const VAL: u128 = 42;
+        const VAL_1: u128 = VAL + 1;
+        const VAL_2: u128 = VAL + 2;
+        m!(0, ..core::u128::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+}
+
+mod signed {
+    fn i8() {
+        const ALMOST_MAX: i8 = core::i8::MAX - 1;
+        const ALMOST_MIN: i8 = core::i8::MIN + 1;
+        const VAL: i8 = 42;
+        const VAL_1: i8 = VAL + 1;
+        const VAL_2: i8 = VAL + 2;
+        m!(0, ..core::i8::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i16() {
+        const ALMOST_MAX: i16 = core::i16::MAX - 1;
+        const ALMOST_MIN: i16 = core::i16::MIN + 1;
+        const VAL: i16 = 42;
+        const VAL_1: i16 = VAL + 1;
+        const VAL_2: i16 = VAL + 2;
+        m!(0, ..core::i16::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i32() {
+        const ALMOST_MAX: i32 = core::i32::MAX - 1;
+        const ALMOST_MIN: i32 = core::i32::MIN + 1;
+        const VAL: i32 = 42;
+        const VAL_1: i32 = VAL + 1;
+        const VAL_2: i32 = VAL + 2;
+        m!(0, ..core::i32::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i64() {
+        const ALMOST_MAX: i64 = core::i64::MAX - 1;
+        const ALMOST_MIN: i64 = core::i64::MIN + 1;
+        const VAL: i64 = 42;
+        const VAL_1: i64 = VAL + 1;
+        const VAL_2: i64 = VAL + 2;
+        m!(0, ..core::i64::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+    fn i128() {
+        const ALMOST_MAX: i128 = core::i128::MAX - 1;
+        const ALMOST_MIN: i128 = core::i128::MIN + 1;
+        const VAL: i128 = 42;
+        const VAL_1: i128 = VAL + 1;
+        const VAL_2: i128 = VAL + 2;
+        m!(0, ..core::i128::MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns
+        m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+        m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns
+        m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
new file mode 100644
index 0000000..26d0cf9
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -0,0 +1,547 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
+   |
+LL |     m!(0f32, core::f32::NEG_INFINITY..);
+   |        ^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:17:8
+   |
+LL |     m!(0f32, ..core::f32::INFINITY);
+   |        ^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
+   |
+LL |     m!('a', ..core::char::MAX);
+   |        ^^^ pattern `'\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
+   |
+LL |     m!('a', ..ALMOST_MAX);
+   |        ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
+   |
+LL |     m!('a', ALMOST_MIN..);
+   |        ^^^ pattern `'\u{0}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
+   |
+LL |     m!('a', ..=ALMOST_MAX);
+   |        ^^^ pattern `'\u{10ffff}'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'b'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
+   |
+LL |     m!('a', ..=VAL | VAL_2..);
+   |        ^^^ pattern `'b'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `'b'` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:31:8
+   |
+LL |     m!('a', ..VAL_1 | VAL_2..);
+   |        ^^^ pattern `'b'` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
+   |
+LL |         m!(0, ..core::u8::MAX);
+   |            ^ pattern `std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `254u8..=std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `254u8..=std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:46:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
+   |
+LL |         m!(0, ..core::u16::MAX);
+   |            ^ pattern `std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `65534u16..=std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `65534u16..=std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:59:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
+   |
+LL |         m!(0, ..core::u32::MAX);
+   |            ^ pattern `std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `4294967294u32..=std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `4294967294u32..=std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:72:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
+   |
+LL |         m!(0, ..core::u64::MAX);
+   |            ^ pattern `std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `18446744073709551614u64..=std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `18446744073709551614u64..=std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:85:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
+   |
+LL |         m!(0, ..core::u128::MAX);
+   |            ^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `0u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43u128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:98:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
+   |
+LL |         m!(0, ..core::i8::MAX);
+   |            ^ pattern `std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `126i8..=std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `126i8..=std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i8::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i8` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:114:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
+   |
+LL |         m!(0, ..core::i16::MAX);
+   |            ^ pattern `std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `32766i16..=std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `32766i16..=std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i16::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i16::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i16` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:127:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
+   |
+LL |         m!(0, ..core::i32::MAX);
+   |            ^ pattern `std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `2147483646i32..=std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `2147483646i32..=std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i32::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i32` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:140:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i32` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
+   |
+LL |         m!(0, ..core::i64::MAX);
+   |            ^ pattern `std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `9223372036854775806i64..=std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `9223372036854775806i64..=std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i64::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i64::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i64` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:153:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i64` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
+   |
+LL |         m!(0, ..core::i128::MAX);
+   |            ^ pattern `std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
+   |
+LL |         m!(0, ..ALMOST_MAX);
+   |            ^ pattern `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MIN` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
+   |
+LL |         m!(0, ALMOST_MIN..);
+   |            ^ pattern `std::i128::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
+   |
+LL |         m!(0, ..=ALMOST_MAX);
+   |            ^ pattern `std::i128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
+   |
+LL |         m!(0, ..=VAL | VAL_2..);
+   |            ^ pattern `43i128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `43i128` not covered
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:166:12
+   |
+LL |         m!(0, ..VAL_1 | VAL_2..);
+   |            ^ pattern `43i128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 68 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
new file mode 100644
index 0000000..efac0df
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
@@ -0,0 +1,49 @@
+// check-pass
+
+// Test various exhaustive matches for `X..`, `..=X` and `..X` ranges.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {}
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+macro_rules! test_int {
+    ($s:expr, $min:path, $max:path) => {
+        m!($s, $min..);
+        m!($s, $min..5 | 5..);
+        m!($s, ..5 | 5..);
+        m!($s, ..=4 | 5..);
+        m!($s, ..=$max);
+        m!($s, ..$max | $max);
+        m!(($s, true), (..5, true) | (5.., true) | ($min.., false));
+    }
+}
+
+fn unsigned_int() {
+    test_int!(0u8, core::u8::MIN, core::u8::MAX);
+    test_int!(0u16, core::u16::MIN, core::u16::MAX);
+    test_int!(0u32, core::u32::MIN, core::u32::MAX);
+    test_int!(0u64, core::u64::MIN, core::u64::MAX);
+    test_int!(0u128, core::u128::MIN, core::u128::MAX);
+}
+
+fn signed_int() {
+    test_int!(0i8, core::i8::MIN, core::i8::MAX);
+    test_int!(0i16, core::i16::MIN, core::i16::MAX);
+    test_int!(0i32, core::i32::MIN, core::i32::MAX);
+    test_int!(0i64, core::i64::MIN, core::i64::MAX);
+    test_int!(0i128, core::i128::MIN, core::i128::MAX);
+}
+
+fn khar() {
+    m!('a', ..=core::char::MAX);
+    m!('a', '\u{0}'..);
+    m!('a', ..='\u{D7FF}' | '\u{E000}'..);
+    m!('a', ..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
new file mode 100644
index 0000000..904efda
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
@@ -0,0 +1,54 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    m!(0, ..core::u8::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u16::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u32::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u64::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::u128::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!(0, ..core::i8::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i16::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i32::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i64::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0, ..core::i128::MIN);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!(0f32, ..core::f32::NEG_INFINITY);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+    m!(0f64, ..core::f64::NEG_INFINITY);
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+
+    m!('a', ..'\u{0}');
+    //~^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
new file mode 100644
index 0000000..b536e1b
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
@@ -0,0 +1,159 @@
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+   |
+LL |     m!(0, ..core::u8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+   |
+LL |     m!(0, ..core::u16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+   |
+LL |     m!(0, ..core::u32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+   |
+LL |     m!(0, ..core::u64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+   |
+LL |     m!(0, ..core::u128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+   |
+LL |     m!(0, ..core::i8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+   |
+LL |     m!(0, ..core::i16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+   |
+LL |     m!(0, ..core::i32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+   |
+LL |     m!(0, ..core::i64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+   |
+LL |     m!(0, ..core::i128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+   |
+LL |     m!(0f32, ..core::f32::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+   |
+LL |     m!(0f64, ..core::f64::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+   |
+LL |     m!('a', ..'\u{0}');
+   |             ^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+   |
+LL |     m!(0, ..core::u8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+   |
+LL |     m!(0, ..core::u16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+   |
+LL |     m!(0, ..core::u32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+   |
+LL |     m!(0, ..core::u64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+   |
+LL |     m!(0, ..core::u128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+   |
+LL |     m!(0, ..core::i8::MIN);
+   |           ^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+   |
+LL |     m!(0, ..core::i16::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+   |
+LL |     m!(0, ..core::i32::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+   |
+LL |     m!(0, ..core::i64::MIN);
+   |           ^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+   |
+LL |     m!(0, ..core::i128::MIN);
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+   |
+LL |     m!(0f32, ..core::f32::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+   |
+LL |     m!(0f64, ..core::f64::NEG_INFINITY);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+   |
+LL |     m!('a', ..'\u{0}');
+   |             ^^^^^^^^^
+
+error: aborting due to 26 previous errors
+
+For more information about this error, try `rustc --explain E0579`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
new file mode 100644
index 0000000..daed775
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
@@ -0,0 +1,32 @@
+// Test that `...X` range-to patterns are syntactically invalid.
+//
+// See https://github.com/rust-lang/rust/pull/67258#issuecomment-565656155
+// for the reason why. To summarize, we might want to introduce `...expr` as
+// an expression form for splatting (or "untupling") in an expression context.
+// While there is no syntactic ambiguity with `...X` in a pattern context,
+// there's a potential confusion factor here, and we would prefer to keep patterns
+// and expressions in-sync. As such, we do not allow `...X` in patterns either.
+
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match scrutinee {
+        ...X => {} //~ ERROR range-to patterns with `...` are not allowed
+        ...0 => {} //~ ERROR range-to patterns with `...` are not allowed
+        ...'a' => {} //~ ERROR range-to patterns with `...` are not allowed
+        ...0.0f32 => {} //~ ERROR range-to patterns with `...` are not allowed
+    }
+}
+
+fn syntax2() {
+    macro_rules! mac {
+        ($e:expr) => {
+            let ...$e; //~ ERROR range-to patterns with `...` are not allowed
+        }
+    }
+
+    mac!(0);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
new file mode 100644
index 0000000..ba2e7ea
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
@@ -0,0 +1,35 @@
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9
+   |
+LL |         ...X => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9
+   |
+LL |         ...0 => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:19:9
+   |
+LL |         ...'a' => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:20:9
+   |
+LL |         ...0.0f32 => {}
+   |         ^^^ help: use `..=` instead
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:27:17
+   |
+LL |             let ...$e;
+   |                 ^^^ help: use `..=` instead
+...
+LL |     mac!(0);
+   |     -------- in this macro invocation
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
new file mode 100644
index 0000000..9ace0c3
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
@@ -0,0 +1,26 @@
+// Test `X...` and `X..=` range patterns not being allowed syntactically.
+// FIXME(Centril): perhaps these should be semantic restrictions.
+
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn foo() {
+    if let 0... = 1 {} //~ ERROR inclusive range with no end
+    if let 0..= = 1 {} //~ ERROR inclusive range with no end
+    const X: u8 = 0;
+    if let X... = 1 {} //~ ERROR inclusive range with no end
+    if let X..= = 1 {} //~ ERROR inclusive range with no end
+}
+
+fn bar() {
+    macro_rules! mac {
+        ($e:expr) => {
+            let $e...; //~ ERROR inclusive range with no end
+            let $e..=; //~ ERROR inclusive range with no end
+        }
+    }
+
+    mac!(0);
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
new file mode 100644
index 0000000..2bdb8ea
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
@@ -0,0 +1,57 @@
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13
+   |
+LL |     if let 0... = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13
+   |
+LL |     if let 0..= = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:13:13
+   |
+LL |     if let X... = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:14:13
+   |
+LL |     if let X..= = 1 {}
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19
+   |
+LL |             let $e...;
+   |                   ^^^ help: use `..` instead
+...
+LL |     mac!(0);
+   |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-inclusive-no-end.rs:21:19
+   |
+LL |             let $e..=;
+   |                   ^^^ help: use `..` instead
+...
+LL |     mac!(0);
+   |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
new file mode 100644
index 0000000..f054bbe
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
@@ -0,0 +1,26 @@
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match &0 {
+        &0.. | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &0..= | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~| ERROR inclusive range with no end
+        &0... | _ => {}
+        //~^ ERROR inclusive range with no end
+    }
+
+    match &0 {
+        &..0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &..=0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        &...0 | _ => {}
+        //~^ ERROR the range pattern here has ambiguous interpretation
+        //~| ERROR range-to patterns with `...` are not allowed
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
new file mode 100644
index 0000000..a5f7c39
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
@@ -0,0 +1,55 @@
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10
+   |
+LL |         &0.. | _ => {}
+   |          ^^^ help: add parentheses to clarify the precedence: `(0 ..)`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11
+   |
+LL |         &0..= | _ => {}
+   |           ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10
+   |
+LL |         &0..= | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(0 ..=)`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11
+   |
+LL |         &0... | _ => {}
+   |           ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10
+   |
+LL |         &..0 | _ => {}
+   |          ^^^ help: add parentheses to clarify the precedence: `(..0)`
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10
+   |
+LL |         &..=0 | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
+
+error: range-to patterns with `...` are not allowed
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
+   |
+LL |         &...0 | _ => {}
+   |          ^^^ help: use `..=` instead
+
+error: the range pattern here has ambiguous interpretation
+  --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
+   |
+LL |         &...0 | _ => {}
+   |          ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
new file mode 100644
index 0000000..416c59a
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
@@ -0,0 +1,160 @@
+// run-pass
+
+// Test half-open range patterns against their expression equivalents
+// via `.contains(...)` and make sure the dynamic semantics match.
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+#![allow(illegal_floating_point_literal_pattern)]
+#![allow(unreachable_patterns)]
+
+macro_rules! yes {
+    ($scrutinee:expr, $($t:tt)+) => {
+        {
+            let m = match $scrutinee { $($t)+ => true, _ => false, };
+            let c = ($($t)+).contains(&$scrutinee);
+            assert_eq!(m, c);
+            m
+        }
+    }
+}
+
+fn range_to_inclusive() {
+    // `..=X` (`RangeToInclusive`-equivalent):
+    //---------------------------------------
+
+    // u8; `..=X`
+    assert!(yes!(core::u8::MIN, ..=core::u8::MIN));
+    assert!(yes!(core::u8::MIN, ..=5));
+    assert!(yes!(5u8, ..=5));
+    assert!(!yes!(6u8, ..=5));
+
+    // i16; `..=X`
+    assert!(yes!(core::i16::MIN, ..=core::i16::MIN));
+    assert!(yes!(core::i16::MIN, ..=0));
+    assert!(yes!(core::i16::MIN, ..=-5));
+    assert!(yes!(-5, ..=-5));
+    assert!(!yes!(-4, ..=-5));
+
+    // char; `..=X`
+    assert!(yes!('\u{0}', ..='\u{0}'));
+    assert!(yes!('\u{0}', ..='a'));
+    assert!(yes!('a', ..='a'));
+    assert!(!yes!('b', ..='a'));
+
+    // f32; `..=X`
+    assert!(yes!(core::f32::NEG_INFINITY, ..=core::f32::NEG_INFINITY));
+    assert!(yes!(core::f32::NEG_INFINITY, ..=1.0f32));
+    assert!(yes!(1.5f32, ..=1.5f32));
+    assert!(!yes!(1.6f32, ..=-1.5f32));
+
+    // f64; `..=X`
+    assert!(yes!(core::f64::NEG_INFINITY, ..=core::f64::NEG_INFINITY));
+    assert!(yes!(core::f64::NEG_INFINITY, ..=1.0f64));
+    assert!(yes!(1.5f64, ..=1.5f64));
+    assert!(!yes!(1.6f64, ..=-1.5f64));
+}
+
+fn range_to() {
+    // `..X` (`RangeTo`-equivalent):
+    //-----------------------------
+
+    // u8; `..X`
+    assert!(yes!(0u8, ..1));
+    assert!(yes!(0u8, ..5));
+    assert!(!yes!(5u8, ..5));
+    assert!(!yes!(6u8, ..5));
+
+    // u8; `..X`
+    const NU8: u8 = core::u8::MIN + 1;
+    assert!(yes!(core::u8::MIN, ..NU8));
+    assert!(yes!(0u8, ..5));
+    assert!(!yes!(5u8, ..5));
+    assert!(!yes!(6u8, ..5));
+
+    // i16; `..X`
+    const NI16: i16 = core::i16::MIN + 1;
+    assert!(yes!(core::i16::MIN, ..NI16));
+    assert!(yes!(core::i16::MIN, ..5));
+    assert!(yes!(-6, ..-5));
+    assert!(!yes!(-5, ..-5));
+
+    // char; `..X`
+    assert!(yes!('\u{0}', ..'\u{1}'));
+    assert!(yes!('\u{0}', ..'a'));
+    assert!(yes!('a', ..'b'));
+    assert!(!yes!('a', ..'a'));
+    assert!(!yes!('b', ..'a'));
+
+    // f32; `..X`
+    assert!(yes!(core::f32::NEG_INFINITY, ..1.0f32));
+    assert!(!yes!(1.5f32, ..1.5f32));
+    const E32: f32 = 1.5f32 + core::f32::EPSILON;
+    assert!(yes!(1.5f32, ..E32));
+    assert!(!yes!(1.6f32, ..1.5f32));
+
+    // f64; `..X`
+    assert!(yes!(core::f64::NEG_INFINITY, ..1.0f64));
+    assert!(!yes!(1.5f64, ..1.5f64));
+    const E64: f64 = 1.5f64 + core::f64::EPSILON;
+    assert!(yes!(1.5f64, ..E64));
+    assert!(!yes!(1.6f64, ..1.5f64));
+}
+
+fn range_from() {
+    // `X..` (`RangeFrom`-equivalent):
+    //--------------------------------
+
+    // u8; `X..`
+    assert!(yes!(core::u8::MIN, core::u8::MIN..));
+    assert!(yes!(core::u8::MAX, core::u8::MIN..));
+    assert!(!yes!(core::u8::MIN, 1..));
+    assert!(!yes!(4, 5..));
+    assert!(yes!(5, 5..));
+    assert!(yes!(6, 5..));
+    assert!(yes!(core::u8::MAX, core::u8::MAX..));
+
+    // i16; `X..`
+    assert!(yes!(core::i16::MIN, core::i16::MIN..));
+    assert!(yes!(core::i16::MAX, core::i16::MIN..));
+    const NI16: i16 = core::i16::MIN + 1;
+    assert!(!yes!(core::i16::MIN, NI16..));
+    assert!(!yes!(-4, 5..));
+    assert!(yes!(-4, -4..));
+    assert!(yes!(-3, -4..));
+    assert!(yes!(core::i16::MAX, core::i16::MAX..));
+
+    // char; `X..`
+    assert!(yes!('\u{0}', '\u{0}'..));
+    assert!(yes!(core::char::MAX, '\u{0}'..));
+    assert!(yes!('a', 'a'..));
+    assert!(yes!('b', 'a'..));
+    assert!(!yes!('a', 'b'..));
+    assert!(yes!(core::char::MAX, core::char::MAX..));
+
+    // f32; `X..`
+    assert!(yes!(core::f32::NEG_INFINITY, core::f32::NEG_INFINITY..));
+    assert!(yes!(core::f32::INFINITY, core::f32::NEG_INFINITY..));
+    assert!(!yes!(core::f32::NEG_INFINITY, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, 1.0f32..));
+    assert!(!yes!(1.0f32 - core::f32::EPSILON, 1.0f32..));
+    assert!(yes!(1.0f32, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, 1.0f32..));
+    assert!(yes!(core::f32::INFINITY, core::f32::INFINITY..));
+
+    // f64; `X..`
+    assert!(yes!(core::f64::NEG_INFINITY, core::f64::NEG_INFINITY..));
+    assert!(yes!(core::f64::INFINITY, core::f64::NEG_INFINITY..));
+    assert!(!yes!(core::f64::NEG_INFINITY, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, 1.0f64..));
+    assert!(!yes!(1.0f64 - core::f64::EPSILON, 1.0f64..));
+    assert!(yes!(1.0f64, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, 1.0f64..));
+    assert!(yes!(core::f64::INFINITY, core::f64::INFINITY..));
+}
+
+fn main() {
+    range_to_inclusive();
+    range_to();
+    range_from();
+}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
new file mode 100644
index 0000000..8bb98d3
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+// Test the parsing of half-open ranges.
+
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    match scrutinee {
+        X.. | 0.. | 'a'.. | 0.0f32.. => {}
+        ..=X | ..X => {}
+        ..=0 | ..0 => {}
+        ..='a' | ..'a' => {}
+        ..=0.0f32 | ..0.0f32 => {}
+    }
+}
+
+fn syntax2() {
+    macro_rules! mac {
+        ($e:expr) => {
+            match 0u8 { ..$e => {}, _ => {} }
+            match 0u8 { ..=$e => {}, _ => {} }
+            match 0u8 { $e.. => {}, _ => {} }
+        }
+    }
+    mac!(42u8);
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-4.rs b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
new file mode 100644
index 0000000..bd79536
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    const PAT: u8 = 1;
+
+    match 0 {
+        (.. PAT) => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.rs b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
new file mode 100644
index 0000000..613d907
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
@@ -0,0 +1,10 @@
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    const PAT: u8 = 1;
+
+    match (0, 1) {
+        (PAT ..) => {} //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
new file mode 100644
index 0000000..307ad71
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-5.rs:8:10
+   |
+LL |     match (0, 1) {
+   |           ------ this expression has type `({integer}, {integer})`
+LL |         (PAT ..) => {}
+   |          ^^^ expected tuple, found `u8`
+   |
+   = note: expected tuple `({integer}, {integer})`
+               found type `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
index afa07cc..303c0cc 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
@@ -39,6 +39,7 @@
 ...  |
 LL | |     foo_hrtb_bar_not(&mut t);
    | |     ------------------------ recursive call site
+LL | |
 LL | | }
    | |_^ cannot return without recursing
    |
@@ -62,7 +63,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: function cannot return without recursing
-  --> $DIR/hrtb-perfect-forwarding.rs:49:1
+  --> $DIR/hrtb-perfect-forwarding.rs:50:1
    |
 LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
 LL | |     where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
index 63db695..0303a76 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
@@ -44,6 +44,7 @@
     // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
     // clause only specifies `T : Bar<&'b isize>`.
     foo_hrtb_bar_not(&mut t); //~ ERROR mismatched types
+                              //~| ERROR mismatched types
 }
 
 fn foo_hrtb_bar_hrtb<T>(mut t: T)
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
index 9bc8cd6..1ceb0c9 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -7,6 +7,15 @@
    = note: expected type `Bar<&'a isize>`
               found type `Bar<&'b isize>`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+   |
+LL |     foo_hrtb_bar_not(&mut t);
+   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `Bar<&'a isize>`
+              found type `Bar<&'b isize>`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index cd1272d..c736c54 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -11,10 +11,46 @@
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:116:17
+  --> $DIR/issue-30786.rs:114:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:114:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:114:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
    |
 LL |     let count = filter.count(); // Assert that we still have a valid stream.
    |                 ^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:119:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
index 34d6b19f..c656f843 100644
--- a/src/test/ui/hrtb/issue-30786.rs
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -113,7 +113,12 @@
     //[migrate]~| NOTE  implementation of `Stream` is not general enough
     let filter = map.filter(|x: &_| true);
     //[nll]~^ ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
     let count = filter.count(); // Assert that we still have a valid stream.
     //[nll]~^ ERROR higher-ranked subtype error
-
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
+    //[nll]~| ERROR higher-ranked subtype error
 }
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 736369d..5d75f50 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -15,7 +15,7 @@
 LL |         Vec::new();
    |         ^^^ use of undeclared type or module `Vec`
 
-error[E0599]: no method named `clone` found for type `()` in the current scope
+error[E0599]: no method named `clone` found for unit type `()` in the current scope
   --> $DIR/no_implicit_prelude.rs:12:12
    |
 LL |     fn f() { ::bar::m!(); }
diff --git a/src/test/ui/hygiene/privacy.stderr b/src/test/ui/hygiene/privacy.stderr
index 80fb4dd..0649dc0 100644
--- a/src/test/ui/hygiene/privacy.stderr
+++ b/src/test/ui/hygiene/privacy.stderr
@@ -2,7 +2,13 @@
   --> $DIR/privacy.rs:16:14
    |
 LL |         foo::f()
-   |              ^
+   |              ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/privacy.rs:4:5
+   |
+LL |     fn f() {}
+   |     ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
index a116c5b..15c4acb 100644
--- a/src/test/ui/hygiene/trait_items.rs
+++ b/src/test/ui/hygiene/trait_items.rs
@@ -14,7 +14,7 @@
 }
 
 mod baz {
-    pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
+    pub macro m() { ().f() } //~ ERROR no method named `f` found
     fn f() { ::bar::m!(); }
 }
 
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
index c3ce484..8e36092 100644
--- a/src/test/ui/hygiene/trait_items.stderr
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `()` in the current scope
+error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/trait_items.rs:17:24
    |
 LL |     fn f() { ::baz::m!(); }
diff --git a/src/test/ui/ignore-all-the-things.rs b/src/test/ui/ignore-all-the-things.rs
index 8c046a2..5980e1a 100644
--- a/src/test/ui/ignore-all-the-things.rs
+++ b/src/test/ui/ignore-all-the-things.rs
@@ -3,9 +3,6 @@
 #![allow(non_shorthand_field_patterns)]
 #![allow(dead_code)]
 #![allow(unused_variables)]
-// pretty-expanded FIXME #23616
-
-#![feature(slice_patterns)]
 
 struct Foo(isize, isize, isize, isize);
 struct Bar{a: isize, b: isize, c: isize, d: isize}
diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
index 492ca87..14c53f9 100644
--- a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
@@ -2,13 +2,23 @@
   --> $DIR/assoc-type.rs:11:19
    |
 LL |     type Output = &i32;
-   |                   ^ expected lifetime parameter
+   |                   ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type Output<'lifetime> = &'lifetime i32;
+   |                ^^^^^^^^^^^   ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/assoc-type.rs:16:20
    |
 LL |     type Output = &'_ i32;
-   |                    ^^ expected lifetime parameter
+   |                    ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type Output<'lifetime> = &'lifetime i32;
+   |                ^^^^^^^^^^^    ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index 1c601bc..a601283 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -12,6 +12,7 @@
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
     //~| ERROR cycle detected
+    //~| ERROR cycle detected
     send(cycle2().clone());
     //~^ ERROR cannot be sent between threads safely
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index d11941f..0ebaac8 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -11,12 +11,12 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:21:16
+  --> $DIR/auto-trait-leak.rs:22:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:21:1
+  --> $DIR/auto-trait-leak.rs:22:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,12 +47,47 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:21:16
+  --> $DIR/auto-trait-leak.rs:22:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:21:1
+  --> $DIR/auto-trait-leak.rs:22:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/auto-trait-leak.rs:1:1
+   |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+...  |
+LL | |     Rc::new(String::from("foo"))
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0`
+  --> $DIR/auto-trait-leak.rs:12:16
+   |
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
+   |
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+note: ...which requires processing `cycle2::{{opaque}}#0`...
+  --> $DIR/auto-trait-leak.rs:22:16
+   |
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:22:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,18 +105,21 @@
    | |_^
 
 error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:15:5
+  --> $DIR/auto-trait-leak.rs:16:5
    |
 LL | fn send<T: Send>(_: T) {}
    |    ----    ---- required by this bound in `send`
 ...
 LL |     send(cycle2().clone());
    |     ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
+...
+LL | fn cycle2() -> impl Clone {
+   |                ---------- within this `impl std::clone::Clone`
    |
    = 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`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0391.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
index d163e1d..a93b3db 100644
--- a/src/test/ui/impl-trait/auto-trait-leak2.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
   --> $DIR/auto-trait-leak2.rs:13:5
    |
+LL | fn before() -> impl Fn(i32) {
+   |                ------------ within this `impl std::ops::Fn<(i32,)>`
+...
 LL | fn send<T: Send>(_: T) {}
    |    ----    ---- required by this bound in `send`
 ...
@@ -19,6 +22,9 @@
 ...
 LL |     send(after());
    |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+...
+LL | fn after() -> impl Fn(i32) {
+   |               ------------ within this `impl std::ops::Fn<(i32,)>`
    |
    = 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>>]`
diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr
index 644d26b..1605f34 100644
--- a/src/test/ui/impl-trait/bindings-opaque.stderr
+++ b/src/test/ui/impl-trait/bindings-opaque.stderr
@@ -6,19 +6,19 @@
    |
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $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
+error[E0599]: no method named `count_ones` found for opaque 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
+error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:15:17
    |
 LL |     let _ = foo.count_ones();
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
new file mode 100644
index 0000000..b70a51d
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
@@ -0,0 +1,34 @@
+#![allow(bare_trait_objects)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn fuz() -> (usize, Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bar() -> (usize, dyn Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bap() -> Trait { Struct }
+//~^ ERROR E0746
+fn ban() -> dyn Trait { Struct }
+//~^ ERROR E0746
+fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0277
+// Suggest using `Box<dyn Trait>`
+fn bal() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return Struct;
+    }
+    42
+}
+
+// Suggest using `impl Trait`
+fn bat() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
new file mode 100644
index 0000000..977a7ef
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -0,0 +1,113 @@
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |                                   ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^   ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+   |             |
+   |             doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |                                       ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^^^^^   ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+   |             |
+   |             doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
+   |
+LL | fn bap() -> Trait { Struct }
+   |             ^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn bap() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
+   |
+LL | fn ban() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn ban() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
+   |
+LL | fn bak() -> dyn Trait { unimplemented!() }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
+   |
+LL | fn bal() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+   |
+LL | fn bal() -> Box<dyn Trait> {
+LL |     if true {
+LL |         return Box::new(Struct);
+LL |     }
+LL |     Box::new(42)
+   |
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
+   |
+LL | fn bat() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
+   |
+LL | fn bat() -> impl Trait {
+   |             ^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0746.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index e53524e..9178358 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -9,6 +9,12 @@
 LL |     }
 LL |     0_u32
    |     ^^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: if the trait `Foo` were object safe, you could return a boxed trait object
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0277]: cannot add `impl Foo` to `u32`
   --> $DIR/equality.rs:24:11
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 312976b..b882514 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:25:18
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          -------- the found opaque type
+...
 LL |     let _: u32 = hide(0_u32);
    |            ---   ^^^^^^^^^^^ expected `u32`, found opaque type
    |            |
@@ -12,6 +15,9 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:31:18
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          -------- the found opaque type
+...
 LL |     let _: i32 = Leak::leak(hide(0_i32));
    |            ---   ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
    |            |
@@ -25,6 +31,12 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:38:10
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          --------
+   |                          |
+   |                          the expected opaque type
+   |                          the found opaque type
+...
 LL |     x = (x.1,
    |          ^^^ expected `u32`, found `i32`
    |
@@ -34,6 +46,12 @@
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:41:10
    |
+LL | fn hide<T: Foo>(x: T) -> impl Foo {
+   |                          --------
+   |                          |
+   |                          the expected opaque type
+   |                          the found opaque type
+...
 LL |          x.0);
    |          ^^^ expected `i32`, found `u32`
    |
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
index 2bff01b..41f48cb 100644
--- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs
@@ -18,5 +18,5 @@
     let f1 = Bar;
 
     f1.foo(1usize);
-    //~^ error: method named `foo` found for type `Bar` in the current scope
+    //~^ error: method named `foo` found for struct `Bar` in the current scope
 }
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 441191b..5741797 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
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `Bar` in the current scope
+error[E0599]: no method named `foo` found for struct `Bar` in the current scope
   --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8
    |
 LL | struct Bar;
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 fb870d6..7f2eb0c 100644
--- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `is_empty` found for type `Foo` in the current scope
+error[E0599]: no method named `is_empty` found for struct `Foo` in the current scope
   --> $DIR/method-suggestion-no-duplication.rs:7:15
    |
 LL | struct Foo;
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.rs b/src/test/ui/impl-trait/no-method-suggested-traits.rs
index c912873..c8abc2d 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.rs
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.rs
@@ -25,7 +25,7 @@
     //~|items from traits can only be used if the trait is in scope
     std::rc::Rc::new(&mut Box::new(&1u32)).method();
     //~^items from traits can only be used if the trait is in scope
-    //~| ERROR no method named `method` found for type
+    //~| ERROR no method named `method` found for struct
 
     'a'.method();
     //~^ ERROR no method named
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index f0a03e1..da25617 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -16,7 +16,7 @@
 LL | use no_method_suggested_traits::Reexported;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&u32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:26:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method();
@@ -46,7 +46,7 @@
 LL | use foo::Bar;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:32:43
    |
 LL |         fn method(&self) {}
@@ -78,7 +78,7 @@
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&i32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:37:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method();
@@ -90,7 +90,7 @@
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 
-error[E0599]: no method named `method` found for type `Foo` in the current scope
+error[E0599]: no method named `method` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:40:9
    |
 LL | struct Foo;
@@ -106,7 +106,7 @@
            candidate #3: `no_method_suggested_traits::qux::PrivPub`
            candidate #4: `no_method_suggested_traits::Reexported`
 
-error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:42:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method();
@@ -129,7 +129,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:47:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u64)).method2();
@@ -139,7 +139,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
@@ -149,7 +149,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
@@ -159,7 +159,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
@@ -169,7 +169,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method2` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
@@ -179,7 +179,7 @@
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
            candidate #1: `foo::Bar`
 
-error[E0599]: no method named `method3` found for type `Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:59:9
    |
 LL | struct Foo;
@@ -192,7 +192,7 @@
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:61:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method3();
@@ -202,7 +202,7 @@
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:63:12
    |
 LL | enum Bar { X }
@@ -215,7 +215,7 @@
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
            candidate #1: `no_method_suggested_traits::foo::PubPub`
 
-error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `std::rc::Rc<&mut std::boxed::Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:65:46
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
@@ -231,31 +231,31 @@
 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
+error[E0599]: no method named `method3` found for struct `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
+error[E0599]: no method named `method3` found for struct `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
+error[E0599]: no method named `method3` found for struct `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
+error[E0599]: no method named `method3` found for enum `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
+error[E0599]: no method named `method3` found for struct `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();
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
new file mode 100644
index 0000000..ab3086c
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
@@ -0,0 +1,35 @@
+#![allow(bare_trait_objects)]
+trait NotObjectSafe {
+    fn foo() -> Self;
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+    fn foo() -> Self {
+        A
+    }
+}
+
+impl NotObjectSafe for B {
+    fn foo() -> Self {
+        B
+    }
+}
+
+fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object
+    if true {
+        return A;
+    }
+    B
+}
+
+fn cat() -> Box<dyn NotObjectSafe> { //~ ERROR the trait `NotObjectSafe` cannot be made into an
+    if true {
+        return Box::new(A);
+    }
+    Box::new(B)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
new file mode 100644
index 0000000..0c8d267
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
@@ -0,0 +1,21 @@
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:1
+   |
+LL |     fn foo() -> Self;
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn car() -> dyn NotObjectSafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:1
+   |
+LL |     fn foo() -> Self;
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn cat() -> Box<dyn NotObjectSafe> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
new file mode 100644
index 0000000..5035150
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
@@ -0,0 +1,46 @@
+trait NotObjectSafe {
+    fn foo() -> Self;
+}
+
+trait ObjectSafe {
+    fn bar(&self);
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+    fn foo() -> Self {
+        A
+    }
+}
+
+impl NotObjectSafe for B {
+    fn foo() -> Self {
+        B
+    }
+}
+
+impl ObjectSafe for A {
+    fn bar(&self) {}
+}
+
+impl ObjectSafe for B {
+    fn bar(&self) {}
+}
+
+fn can() -> impl NotObjectSafe {
+    if true {
+        return A;
+    }
+    B //~ ERROR mismatched types
+}
+
+fn cat() -> impl ObjectSafe {
+    if true {
+        return A;
+    }
+    B //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
new file mode 100644
index 0000000..dd4260f
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
+   |
+LL | fn can() -> impl NotObjectSafe {
+   |             ------------------ expected because this return type...
+LL |     if true {
+LL |         return A;
+   |                - ...is found to be `A` here
+LL |     }
+LL |     B
+   |     ^ expected struct `A`, found struct `B`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
+
+error[E0308]: mismatched types
+  --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
+   |
+LL | fn cat() -> impl ObjectSafe {
+   |             --------------- expected because this return type...
+LL |     if true {
+LL |         return A;
+   |                - ...is found to be `A` here
+LL |     }
+LL |     B
+   |     ^ expected struct `A`, found struct `B`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn ObjectSafe>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index b7ba0d6..15a028f 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -76,7 +76,7 @@
 LL | fn generator_capture() -> impl Sized {
    |                           ^^^^^^^^^^ expands to a recursive type
    |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]`
+   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {(), ()}]`
 
 error[E0720]: opaque type expands to a recursive type
   --> $DIR/recursive-impl-trait-type-indirect.rs:53:26
@@ -92,7 +92,7 @@
 LL | fn generator_hold() -> impl Sized {
    |                        ^^^^^^^^^^ expands to a recursive type
    |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]`
+   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, (), ()}]`
 
 error[E0720]: opaque type expands to a recursive type
   --> $DIR/recursive-impl-trait-type-indirect.rs:69:26
diff --git a/src/test/ui/import.stderr b/src/test/ui/import.stderr
index 6b320b1..5219ffa 100644
--- a/src/test/ui/import.stderr
+++ b/src/test/ui/import.stderr
@@ -13,11 +13,17 @@
 LL |     use foo;
    |         ^^^ no `foo` in the root
 
-error[E0603]: unresolved item `foo` is private
+error[E0603]: unresolved item import `foo` is private
   --> $DIR/import.rs:15:10
    |
 LL |     zed::foo();
-   |          ^^^
+   |          ^^^ this unresolved item import is private
+   |
+note: the unresolved item import `foo` is defined here
+  --> $DIR/import.rs:10:9
+   |
+LL |     use foo;
+   |         ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs
index defa0e2..1c0d3b4 100644
--- a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.rs
@@ -1,6 +1,6 @@
 extern crate self; //~ ERROR `extern crate self;` requires renaming
 
-#[macro_use] //~ ERROR `macro_use` is not supported on `extern crate self`
+#[macro_use] //~ ERROR `#[macro_use]` is not supported on `extern crate self`
 extern crate self as foo;
 
 fn main() {}
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
index f26bb2f..8f369f1 100644
--- a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr
@@ -4,7 +4,7 @@
 LL | extern crate self;
    | ^^^^^^^^^^^^^^^^^^ help: try: `extern crate self as name;`
 
-error: `macro_use` is not supported on `extern crate self`
+error: `#[macro_use]` is not supported on `extern crate self`
   --> $DIR/extern-crate-self-fail.rs:3:1
    |
 LL | #[macro_use]
diff --git a/src/test/ui/imports/issue-55457.rs b/src/test/ui/imports/issue-55457.rs
index 9c6750f..c1f0488 100644
--- a/src/test/ui/imports/issue-55457.rs
+++ b/src/test/ui/imports/issue-55457.rs
@@ -3,6 +3,8 @@
 
 #[non_existent] //~ ERROR cannot determine resolution for the attribute macro `non_existent`
 #[derive(NonExistent)] //~ ERROR cannot determine resolution for the derive macro `NonExistent`
+                       //~| ERROR cannot determine resolution for the derive macro `NonExistent`
+                       //~| ERROR cannot determine resolution for the derive macro `NonExistent`
 struct S;
 
 fn main() {}
diff --git a/src/test/ui/imports/issue-55457.stderr b/src/test/ui/imports/issue-55457.stderr
index aa103ba..07de3d9 100644
--- a/src/test/ui/imports/issue-55457.stderr
+++ b/src/test/ui/imports/issue-55457.stderr
@@ -29,6 +29,22 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 4 previous errors
+error: cannot determine resolution for the derive macro `NonExistent`
+  --> $DIR/issue-55457.rs:5:10
+   |
+LL | #[derive(NonExistent)]
+   |          ^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `NonExistent`
+  --> $DIR/issue-55457.rs:5:10
+   |
+LL | #[derive(NonExistent)]
+   |          ^^^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-55884-2.rs b/src/test/ui/imports/issue-55884-2.rs
index 1b4f652..75bb420 100644
--- a/src/test/ui/imports/issue-55884-2.rs
+++ b/src/test/ui/imports/issue-55884-2.rs
@@ -9,6 +9,6 @@
     use ParseOptions;
 }
 
-pub use parser::ParseOptions; //~ ERROR struct `ParseOptions` is private
+pub use parser::ParseOptions; //~ ERROR struct import `ParseOptions` is private
 
 fn main() {}
diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr
index d3b43783..f16d2ad 100644
--- a/src/test/ui/imports/issue-55884-2.stderr
+++ b/src/test/ui/imports/issue-55884-2.stderr
@@ -1,8 +1,14 @@
-error[E0603]: struct `ParseOptions` is private
+error[E0603]: struct import `ParseOptions` is private
   --> $DIR/issue-55884-2.rs:12:17
    |
 LL | pub use parser::ParseOptions;
-   |                 ^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^ this struct import is private
+   |
+note: the struct import `ParseOptions` is defined here
+  --> $DIR/issue-55884-2.rs:9:9
+   |
+LL |     use ParseOptions;
+   |         ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
index 29e9b8e..37fe0ec 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
@@ -26,6 +26,7 @@
 }
 
 exported!(); //~ ERROR `exported` is ambiguous
+             //~| ERROR `exported` is ambiguous
 
 mod inner2 {
     define_exported!();
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
index 7d01382..c9498fe 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -21,8 +21,31 @@
    |     ^^^^^^^^^
    = help: consider adding an explicit import of `exported` to disambiguate
 
+error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/local-modularized-tricky-fail-1.rs:28:1
+   |
+LL | exported!();
+   | ^^^^^^^^ ambiguous name
+   |
+note: `exported` could refer to the macro defined here
+  --> $DIR/local-modularized-tricky-fail-1.rs:5:5
+   |
+LL | /     macro_rules! exported {
+LL | |         () => ()
+LL | |     }
+   | |_____^
+...
+LL |       define_exported!();
+   |       ------------------- in this macro invocation
+note: `exported` could also refer to the macro imported here
+  --> $DIR/local-modularized-tricky-fail-1.rs:22:5
+   |
+LL | use inner1::*;
+   |     ^^^^^^^^^
+   = help: consider adding an explicit import of `exported` to disambiguate
+
 error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/local-modularized-tricky-fail-1.rs:35:5
+  --> $DIR/local-modularized-tricky-fail-1.rs:36:5
    |
 LL |     panic!();
    |     ^^^^^ ambiguous name
@@ -41,7 +64,7 @@
    = help: use `crate::panic` to refer to this macro unambiguously
 
 error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/local-modularized-tricky-fail-1.rs:46:1
+  --> $DIR/local-modularized-tricky-fail-1.rs:47:1
    |
 LL | include!();
    | ^^^^^^^ ambiguous name
@@ -59,6 +82,6 @@
    |       ------------------ in this macro invocation
    = help: use `crate::include` to refer to this macro unambiguously
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/macros.rs b/src/test/ui/imports/macros.rs
index f2a22ad..f397118 100644
--- a/src/test/ui/imports/macros.rs
+++ b/src/test/ui/imports/macros.rs
@@ -14,6 +14,7 @@
 mod m2 {
     use two_macros::*;
     m! { //~ ERROR ambiguous
+         //~| ERROR ambiguous
         use foo::m;
     }
 }
diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr
index 3b9e6fe..27b34fe 100644
--- a/src/test/ui/imports/macros.stderr
+++ b/src/test/ui/imports/macros.stderr
@@ -5,7 +5,25 @@
    |     ^ ambiguous name
    |
 note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:17:13
+  --> $DIR/macros.rs:18:13
+   |
+LL |         use foo::m;
+   |             ^^^^^^
+note: `m` could also refer to the macro imported here
+  --> $DIR/macros.rs:15:9
+   |
+LL |     use two_macros::*;
+   |         ^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `m` to disambiguate
+
+error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution)
+  --> $DIR/macros.rs:16:5
+   |
+LL |     m! {
+   |     ^ ambiguous name
+   |
+note: `m` could refer to the macro imported here
+  --> $DIR/macros.rs:18:13
    |
 LL |         use foo::m;
    |             ^^^^^^
@@ -17,23 +35,23 @@
    = help: consider adding an explicit import of `m` to disambiguate
 
 error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/macros.rs:29:9
+  --> $DIR/macros.rs:30:9
    |
 LL |         m! {
    |         ^ ambiguous name
    |
 note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:30:17
+  --> $DIR/macros.rs:31:17
    |
 LL |             use two_macros::n as m;
    |                 ^^^^^^^^^^^^^^^^^^
 note: `m` could also refer to the macro imported here
-  --> $DIR/macros.rs:22:9
+  --> $DIR/macros.rs:23:9
    |
 LL |     use two_macros::m;
    |         ^^^^^^^^^^^^^
    = help: use `self::m` to refer to this macro unambiguously
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr
index 4388e2c..b173884 100644
--- a/src/test/ui/imports/reexports.stderr
+++ b/src/test/ui/imports/reexports.stderr
@@ -10,17 +10,29 @@
 LL |         pub use super::foo;
    |                 ^^^^^^^^^^
 
-error[E0603]: module `foo` is private
+error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:33:15
    |
 LL |     use b::a::foo::S;
-   |               ^^^
+   |               ^^^ this module import is private
+   |
+note: the module import `foo` is defined here
+  --> $DIR/reexports.rs:21:17
+   |
+LL |         pub use super::foo; // This is OK since the value `foo` is visible enough.
+   |                 ^^^^^^^^^^
 
-error[E0603]: module `foo` is private
+error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:34:15
    |
 LL |     use b::b::foo::S as T;
-   |               ^^^
+   |               ^^^ this module import is private
+   |
+note: the module import `foo` is defined here
+  --> $DIR/reexports.rs:26:17
+   |
+LL |         pub use super::*; // This is also OK since the value `foo` is visible enough.
+   |                 ^^^^^^^^
 
 warning: glob import doesn't reexport anything because no candidate is public enough
   --> $DIR/reexports.rs:9:17
diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr
index b341e8e..d7280d2 100644
--- a/src/test/ui/imports/unresolved-imports-used.stderr
+++ b/src/test/ui/imports/unresolved-imports-used.stderr
@@ -38,7 +38,13 @@
   --> $DIR/unresolved-imports-used.rs:9:10
    |
 LL | use qux::quz;
-   |          ^^^
+   |          ^^^ this function is private
+   |
+note: the function `quz` is defined here
+  --> $DIR/unresolved-imports-used.rs:5:4
+   |
+LL |    fn quz() {}
+   |    ^^^^^^^^
 
 error: unused import: `qux::quy`
   --> $DIR/unresolved-imports-used.rs:16:5
diff --git a/src/test/ui/impossible_range.rs b/src/test/ui/impossible_range.rs
index 6345af0..21e5c03 100644
--- a/src/test/ui/impossible_range.rs
+++ b/src/test/ui/impossible_range.rs
@@ -1,4 +1,4 @@
-// Make sure that invalid ranges generate an error during HIR lowering, not an ICE
+// Make sure that invalid ranges generate an error during parsing, not an ICE
 
 pub fn main() {
     ..;
@@ -6,12 +6,12 @@
     ..1;
     0..1;
     ..=; //~ERROR inclusive range with no end
-         //~^HELP bounded at the end
+         //~^HELP use `..` instead
 }
 
 fn _foo1() {
     ..=1;
     0..=1;
     0..=; //~ERROR inclusive range with no end
-          //~^HELP bounded at the end
+          //~^HELP use `..` instead
 }
diff --git a/src/test/ui/impossible_range.stderr b/src/test/ui/impossible_range.stderr
index 091fe37..ea2ab0f 100644
--- a/src/test/ui/impossible_range.stderr
+++ b/src/test/ui/impossible_range.stderr
@@ -1,18 +1,18 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/impossible_range.rs:8:8
+  --> $DIR/impossible_range.rs:8:5
    |
 LL |     ..=;
-   |        ^
+   |     ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error[E0586]: inclusive range with no end
-  --> $DIR/impossible_range.rs:15:9
+  --> $DIR/impossible_range.rs:15:6
    |
 LL |     0..=;
-   |         ^
+   |      ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
index 9579abb..5f101a2 100644
--- a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
+++ b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
@@ -2,7 +2,12 @@
   --> $DIR/issue-61124-anon-lifetime-in-struct-declaration.rs:8:19
    |
 LL | struct Heartbreak(Betrayal);
-   |                   ^^^^^^^^ expected lifetime parameter
+   |                   ^^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Heartbreak<'lifetime>(Betrayal<'lifetime>);
+   |                  ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr
index a270dd0..fe656f7 100644
--- a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr
+++ b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr
@@ -1,12 +1,16 @@
 error[E0261]: use of undeclared lifetime name `'test`
   --> $DIR/no_in_band_in_struct.rs:5:9
    |
+LL | struct Foo {
+   |           - help: consider introducing lifetime `'test` here: `<'test>`
 LL |     x: &'test u32,
    |         ^^^^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'test`
   --> $DIR/no_in_band_in_struct.rs:9:10
    |
+LL | enum Bar {
+   |         - help: consider introducing lifetime `'test` here: `<'test>`
 LL |     Baz(&'test u32),
    |          ^^^^^ undeclared lifetime
 
diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
index c307066..bfb20ad 100644
--- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
+++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
@@ -1,6 +1,8 @@
 error[E0261]: use of undeclared lifetime name `'test`
   --> $DIR/no_introducing_in_band_in_locals.rs:5:13
    |
+LL | fn foo(x: &u32) {
+   |       - help: consider introducing lifetime `'test` here: `<'test>`
 LL |     let y: &'test u32 = x;
    |             ^^^^^ undeclared lifetime
 
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index f456755..8c59fbd 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -37,7 +37,7 @@
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
 
-error[E0599]: no method named `bar` found for type `Foo` in the current scope
+error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/infinite-autoderef.rs:26:9
    |
 LL | struct Foo;
diff --git a/src/test/ui/internal/internal-unstable-const.rs b/src/test/ui/internal/internal-unstable-const.rs
new file mode 100644
index 0000000..ce306c8
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-const.rs
@@ -0,0 +1,10 @@
+#![feature(staged_api)]
+#![feature(const_if_match)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+const fn foo() -> i32 {
+    if true { 4 } else { 5 } //~ loops and conditional expressions are not stable in const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/internal/internal-unstable-const.stderr b/src/test/ui/internal/internal-unstable-const.stderr
new file mode 100644
index 0000000..58bbe79
--- /dev/null
+++ b/src/test/ui/internal/internal-unstable-const.stderr
@@ -0,0 +1,12 @@
+error[E0723]: loops and conditional expressions are not stable in const fn
+  --> $DIR/internal-unstable-const.rs:7:5
+   |
+LL |     if true { 4 } else { 5 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/invalid_const_promotion.rs b/src/test/ui/invalid_const_promotion.rs
deleted file mode 100644
index 5d7664c..0000000
--- a/src/test/ui/invalid_const_promotion.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// run-pass
-
-#![allow(unused_mut)]
-// ignore-wasm32
-// ignore-emscripten
-// ignore-sgx no processes
-
-// compile-flags: -C debug_assertions=yes
-
-#![stable(feature = "rustc", since = "1.0.0")]
-#![feature(const_fn, rustc_private, staged_api, rustc_attrs)]
-#![allow(const_err)]
-
-extern crate libc;
-
-use std::env;
-use std::process::{Command, Stdio};
-
-// this will panic in debug mode and overflow in release mode
-//
-// NB we give bar an unused argument because otherwise memoization
-// of the const fn kicks in, causing a different code path in the
-// compiler to be executed (see PR #66294).
-#[stable(feature = "rustc", since = "1.0.0")]
-#[rustc_const_stable(feature = "rustc", since = "1.0.0")]
-#[rustc_promotable]
-const fn bar(_: bool) -> usize { 0 - 1 }
-
-fn foo() {
-    let _: &'static _ = &bar(true);
-}
-
-#[cfg(unix)]
-fn check_status(status: std::process::ExitStatus)
-{
-    use std::os::unix::process::ExitStatusExt;
-
-    assert!(status.signal() == Some(libc::SIGILL)
-            || status.signal() == Some(libc::SIGTRAP)
-            || status.signal() == Some(libc::SIGABRT));
-}
-
-#[cfg(not(unix))]
-fn check_status(status: std::process::ExitStatus)
-{
-    assert!(!status.success());
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 1 && args[1] == "test" {
-        foo();
-        return;
-    }
-
-    let mut p = Command::new(&args[0])
-        .stdout(Stdio::piped())
-        .stdin(Stdio::piped())
-        .arg("test").output().unwrap();
-    check_status(p.status);
-}
diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr
index 80ca051..666fb6a 100644
--- a/src/test/ui/issues/issue-10465.stderr
+++ b/src/test/ui/issues/issue-10465.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&b::B` in the current scope
+error[E0599]: no method named `foo` found for reference `&b::B` in the current scope
   --> $DIR/issue-10465.rs:17:15
    |
 LL |             b.foo();
diff --git a/src/test/ui/issues/issue-10545.stderr b/src/test/ui/issues/issue-10545.stderr
index 59d4fed..4ed7028 100644
--- a/src/test/ui/issues/issue-10545.stderr
+++ b/src/test/ui/issues/issue-10545.stderr
@@ -2,7 +2,13 @@
   --> $DIR/issue-10545.rs:6:14
    |
 LL | fn foo(_: a::S) {
-   |              ^
+   |              ^ this struct is private
+   |
+note: the struct `S` is defined here
+  --> $DIR/issue-10545.rs:2:5
+   |
+LL |     struct S;
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-11593.stderr b/src/test/ui/issues/issue-11593.stderr
index c3e4412..bfb4d31 100644
--- a/src/test/ui/issues/issue-11593.stderr
+++ b/src/test/ui/issues/issue-11593.stderr
@@ -2,7 +2,13 @@
   --> $DIR/issue-11593.rs:7:24
    |
 LL | impl private_trait_xc::Foo for Bar {}
-   |                        ^^^
+   |                        ^^^ this trait is private
+   |
+note: the trait `Foo` is defined here
+  --> $DIR/auxiliary/private-trait-xc.rs:1:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-11680.stderr b/src/test/ui/issues/issue-11680.stderr
index 35cb247..898ac10 100644
--- a/src/test/ui/issues/issue-11680.stderr
+++ b/src/test/ui/issues/issue-11680.stderr
@@ -2,13 +2,25 @@
   --> $DIR/issue-11680.rs:6:21
    |
 LL |     let _b = other::Foo::Bar(1);
-   |                     ^^^
+   |                     ^^^ this enum is private
+   |
+note: the enum `Foo` is defined here
+  --> $DIR/auxiliary/issue-11680.rs:1:1
+   |
+LL | enum Foo {
+   | ^^^^^^^^
 
 error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:9:27
    |
 LL |     let _b = other::test::Foo::Bar(1);
-   |                           ^^^
+   |                           ^^^ this enum is private
+   |
+note: the enum `Foo` is defined here
+  --> $DIR/auxiliary/issue-11680.rs:6:5
+   |
+LL |     enum Foo {
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/issues/issue-12369.rs
index 0866131..0481c1f 100644
--- a/src/test/ui/issues/issue-12369.rs
+++ b/src/test/ui/issues/issue-12369.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/issues/issue-12369.stderr
index f27425e..754b94b 100644
--- a/src/test/ui/issues/issue-12369.stderr
+++ b/src/test/ui/issues/issue-12369.stderr
@@ -1,11 +1,11 @@
 error: unreachable pattern
-  --> $DIR/issue-12369.rs:10:9
+  --> $DIR/issue-12369.rs:9:9
    |
 LL |         &[10,a, ref rest @ ..] => 10
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-12369.rs:2:9
+  --> $DIR/issue-12369.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-12567.rs b/src/test/ui/issues/issue-12567.rs
index 643d9a2..1b2a37d 100644
--- a/src/test/ui/issues/issue-12567.rs
+++ b/src/test/ui/issues/issue-12567.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) {
     match (l1, l2) {
     //~^ ERROR: cannot move out of type `[T]`, a non-copy slice
diff --git a/src/test/ui/issues/issue-12567.stderr b/src/test/ui/issues/issue-12567.stderr
index 9d9a88f..2a88d8f 100644
--- a/src/test/ui/issues/issue-12567.stderr
+++ b/src/test/ui/issues/issue-12567.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
-  --> $DIR/issue-12567.rs:4:11
+  --> $DIR/issue-12567.rs:2:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
@@ -13,7 +13,7 @@
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
-  --> $DIR/issue-12567.rs:4:11
+  --> $DIR/issue-12567.rs:2:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr
index b280de3..f211d62 100644
--- a/src/test/ui/issues/issue-13407.stderr
+++ b/src/test/ui/issues/issue-13407.stderr
@@ -2,7 +2,13 @@
   --> $DIR/issue-13407.rs:6:8
    |
 LL |     A::C = 1;
-   |        ^
+   |        ^ this unit struct is private
+   |
+note: the unit struct `C` is defined here
+  --> $DIR/issue-13407.rs:2:5
+   |
+LL |     struct C;
+   |     ^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-13407.rs:6:12
diff --git a/src/test/ui/issues/issue-13641.stderr b/src/test/ui/issues/issue-13641.stderr
index 8e5001e..f90cb18 100644
--- a/src/test/ui/issues/issue-13641.stderr
+++ b/src/test/ui/issues/issue-13641.stderr
@@ -2,13 +2,25 @@
   --> $DIR/issue-13641.rs:9:8
    |
 LL |     a::Foo::new();
-   |        ^^^
+   |        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/issue-13641.rs:2:5
+   |
+LL |     struct Foo;
+   |     ^^^^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/issue-13641.rs:11:8
    |
 LL |     a::Bar::new();
-   |        ^^^
+   |        ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/issue-13641.rs:4:5
+   |
+LL |     enum Bar {}
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr
index cdb261a..2f31636 100644
--- a/src/test/ui/issues/issue-13853.stderr
+++ b/src/test/ui/issues/issue-13853.stderr
@@ -12,7 +12,7 @@
    = help: type parameters must be constrained to match other types
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error[E0599]: no method named `iter` found for type `&G` in the current scope
+error[E0599]: no method named `iter` found for reference `&G` in the current scope
   --> $DIR/issue-13853.rs:27:23
    |
 LL |     for node in graph.iter() {
diff --git a/src/test/ui/issues/issue-14221.stderr b/src/test/ui/issues/issue-14221.stderr
index 3e5e25a..9864c08 100644
--- a/src/test/ui/issues/issue-14221.stderr
+++ b/src/test/ui/issues/issue-14221.stderr
@@ -3,6 +3,8 @@
    |
 LL |             A => "A",
    |             ^ help: to match on the variant, qualify the path: `E::A`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `B` is named the same as one of the variants of the type `E`
   --> $DIR/issue-14221.rs:15:13
diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/issues/issue-15080.rs
index b11b1cd..4dd6981 100644
--- a/src/test/ui/issues/issue-15080.rs
+++ b/src/test/ui/issues/issue-15080.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let mut x: &[_] = &[1, 2, 3, 4];
diff --git a/src/test/ui/issues/issue-15104.rs b/src/test/ui/issues/issue-15104.rs
index ee97754..47b207e 100644
--- a/src/test/ui/issues/issue-15104.rs
+++ b/src/test/ui/issues/issue-15104.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     assert_eq!(count_members(&[1, 2, 3, 4]), 4);
diff --git a/src/test/ui/issues/issue-16725.stderr b/src/test/ui/issues/issue-16725.stderr
index 562ad94..e0a1ca8 100644
--- a/src/test/ui/issues/issue-16725.stderr
+++ b/src/test/ui/issues/issue-16725.stderr
@@ -2,7 +2,13 @@
   --> $DIR/issue-16725.rs:6:19
    |
 LL |     unsafe { foo::bar(); }
-   |                   ^^^
+   |                   ^^^ this function is private
+   |
+note: the function `bar` is defined here
+  --> $DIR/auxiliary/issue-16725.rs:2:5
+   |
+LL |     fn bar();
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17546.rs b/src/test/ui/issues/issue-17546.rs
index dbfdad2..c93a03c 100644
--- a/src/test/ui/issues/issue-17546.rs
+++ b/src/test/ui/issues/issue-17546.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 use foo::MyEnum::Result;
 use foo::NoResult; // Through a re-export
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index f324291..2d532cd 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -1,8 +1,13 @@
 error[E0573]: expected type, found variant `NoResult`
-  --> $DIR/issue-17546.rs:12:17
+  --> $DIR/issue-17546.rs:16:17
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   | --------------------- similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
@@ -14,7 +19,7 @@
    |                 ^^^^^^
 
 error[E0573]: expected type, found variant `Result`
-  --> $DIR/issue-17546.rs:22:17
+  --> $DIR/issue-17546.rs:26:17
    |
 LL |     fn new() -> Result<foo::MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
@@ -32,7 +37,7 @@
      and 1 other candidate
 
 error[E0573]: expected type, found variant `Result`
-  --> $DIR/issue-17546.rs:28:13
+  --> $DIR/issue-17546.rs:32:13
    |
 LL | fn new() -> Result<foo::MyEnum, String> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
@@ -50,10 +55,15 @@
      and 1 other candidate
 
 error[E0573]: expected type, found variant `NoResult`
-  --> $DIR/issue-17546.rs:33:15
+  --> $DIR/issue-17546.rs:37:15
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL | pub enum Result<T, E> {
+   | --------------------- similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/issues/issue-17718-const-bad-values.rs
index 97657f8..9355c8a 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.rs
+++ b/src/test/ui/issues/issue-17718-const-bad-values.rs
@@ -4,6 +4,7 @@
 static mut S: usize = 3;
 const C2: &'static mut usize = unsafe { &mut S };
 //~^ ERROR: constants cannot refer to statics
+//~| ERROR: constants cannot refer to statics
 //~| ERROR: references in constants may only refer to immutable values
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
index 7e4a62a..e45d8b6 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -7,11 +7,21 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/57349
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-const-bad-values.rs:5:46
    |
 LL | const C2: &'static mut usize = unsafe { &mut S };
    |                                              ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+  --> $DIR/issue-17718-const-bad-values.rs:5:46
+   |
+LL | const C2: &'static mut usize = unsafe { &mut S };
+   |                                              ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0658]: references in constants may only refer to immutable values
   --> $DIR/issue-17718-const-bad-values.rs:5:41
@@ -22,7 +32,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/57349
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0013, E0658.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/issues/issue-17718-const-privacy.stderr
index 0b0de8a..07d825b 100644
--- a/src/test/ui/issues/issue-17718-const-privacy.stderr
+++ b/src/test/ui/issues/issue-17718-const-privacy.stderr
@@ -2,13 +2,25 @@
   --> $DIR/issue-17718-const-privacy.rs:5:8
    |
 LL | use a::B;
-   |        ^
+   |        ^ this constant is private
+   |
+note: the constant `B` is defined here
+  --> $DIR/issue-17718-const-privacy.rs:13:5
+   |
+LL |     const B: usize = 3;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: constant `BAR` is private
   --> $DIR/issue-17718-const-privacy.rs:8:5
    |
 LL |     BAR,
-   |     ^^^
+   |     ^^^ this constant is private
+   |
+note: the constant `BAR` is defined here
+  --> $DIR/auxiliary/issue-17718-const-privacy.rs:4:1
+   |
+LL | const BAR: usize = 3;
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-17718-references.stderr b/src/test/ui/issues/issue-17718-references.stderr
index 27aad9c..e3c3b36 100644
--- a/src/test/ui/issues/issue-17718-references.stderr
+++ b/src/test/ui/issues/issue-17718-references.stderr
@@ -1,20 +1,26 @@
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-references.rs:9:29
    |
 LL | const T2: &'static usize = &S;
    |                             ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-references.rs:14:19
    |
 LL | const T6: usize = S;
    |                   ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-references.rs:19:33
    |
 LL | const T10: Struct = Struct { a: S };
    |                                 ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-17877.rs b/src/test/ui/issues/issue-17877.rs
index fefa3f2..126e01d 100644
--- a/src/test/ui/issues/issue-17877.rs
+++ b/src/test/ui/issues/issue-17877.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     assert_eq!(match [0u8; 1024] {
diff --git a/src/test/ui/issues/issue-18118-2.rs b/src/test/ui/issues/issue-18118-2.rs
index 6d52156..f712a2e 100644
--- a/src/test/ui/issues/issue-18118-2.rs
+++ b/src/test/ui/issues/issue-18118-2.rs
@@ -1,7 +1,6 @@
 pub fn main() {
     const z: &'static isize = {
         static p: isize = 3;
-        &p
-        //~^ ERROR constants cannot refer to statics, use a constant instead
+        &p //~ ERROR constants cannot refer to statics
     };
 }
diff --git a/src/test/ui/issues/issue-18118-2.stderr b/src/test/ui/issues/issue-18118-2.stderr
index d58822f..4fc3ca7 100644
--- a/src/test/ui/issues/issue-18118-2.stderr
+++ b/src/test/ui/issues/issue-18118-2.stderr
@@ -1,8 +1,10 @@
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-18118-2.rs:4:10
    |
 LL |         &p
    |          ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19100.stderr b/src/test/ui/issues/issue-19100.stderr
index 1ab1347..01e5313 100644
--- a/src/test/ui/issues/issue-19100.stderr
+++ b/src/test/ui/issues/issue-19100.stderr
@@ -3,6 +3,8 @@
    |
 LL | Bar if true
    | ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
   --> $DIR/issue-19100.rs:22:1
diff --git a/src/test/ui/issues/issue-19521.stderr b/src/test/ui/issues/issue-19521.stderr
index c15c539..b6847cd 100644
--- a/src/test/ui/issues/issue-19521.stderr
+++ b/src/test/ui/issues/issue-19521.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `homura` found for type `&'static str` in the current scope
+error[E0599]: no method named `homura` found for reference `&'static str` in the current scope
   --> $DIR/issue-19521.rs:2:8
    |
 LL |     "".homura()();
diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr
index fe920c1..b412d7b 100644
--- a/src/test/ui/issues/issue-19692.stderr
+++ b/src/test/ui/issues/issue-19692.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `kaname` found for type `Homura` in the current scope
+error[E0599]: no method named `kaname` found for struct `Homura` in the current scope
   --> $DIR/issue-19692.rs:4:40
    |
 LL | struct Homura;
diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr
index c85ce0e..8a627bc 100644
--- a/src/test/ui/issues/issue-19707.stderr
+++ b/src/test/ui/issues/issue-19707.stderr
@@ -2,17 +2,25 @@
   --> $DIR/issue-19707.rs:3:28
    |
 LL | type Foo = fn(&u8, &u8) -> &u8;
-   |                            ^ expected lifetime parameter
+   |                            ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+help: consider introducing a named lifetime parameter
+   |
+LL | type Foo<'lifetime> = fn(&u8, &u8) -> &'lifetime u8;
+   |         ^^^^^^^^^^^                   ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-19707.rs:5:27
    |
 LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
-   |                           ^ expected lifetime parameter
+   |                           ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+help: consider introducing a named lifetime parameter
+   |
+LL | fn bar<'lifetime, F: Fn(&u8, &u8) -> &'lifetime u8>(f: &F) {}
+   |        ^^^^^^^^^^                    ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-20831-debruijn.rs b/src/test/ui/issues/issue-20831-debruijn.rs
index ef4b158..d0e15cb 100644
--- a/src/test/ui/issues/issue-20831-debruijn.rs
+++ b/src/test/ui/issues/issue-20831-debruijn.rs
@@ -28,6 +28,7 @@
     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
         // Not obvious, but there is an implicit lifetime here -------^
         //~^^ ERROR cannot infer
+        //~| ERROR cannot infer
         //~| ERROR mismatched types
         //~| ERROR mismatched types
         //
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index c7fd134..a4ea1cd 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -102,7 +102,49 @@
    = note: expected  `Publisher<'_>`
               found  `Publisher<'_>`
 
-error: aborting due to 3 previous errors
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
+  --> $DIR/issue-20831-debruijn.rs:26:6
+   |
+LL | impl<'a> Publisher<'a> for MyStruct<'a> {
+   |      ^^
+note: ...so that the types are compatible
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+   = note: expected  `Publisher<'_>`
+              found  `Publisher<'_>`
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0308, E0495.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr
index 4e5cace..efde161 100644
--- a/src/test/ui/issues/issue-21596.stderr
+++ b/src/test/ui/issues/issue-21596.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `to_string` found for type `*const u8` in the current scope
+error[E0599]: no method named `to_string` found for raw pointer `*const u8` in the current scope
   --> $DIR/issue-21596.rs:4:22
    |
 LL |     println!("{}", z.to_string());
diff --git a/src/test/ui/issues/issue-22933-2.rs b/src/test/ui/issues/issue-22933-2.rs
index 98a354b..dfd84b9 100644
--- a/src/test/ui/issues/issue-22933-2.rs
+++ b/src/test/ui/issues/issue-22933-2.rs
@@ -2,7 +2,7 @@
     Pie      = 0x1,
     Apple    = 0x2,
     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-    //~^ ERROR no variant or associated item named `PIE` found for type `Delicious`
+    //~^ ERROR no variant or associated item named `PIE` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr
index 72038ea..584b05e 100644
--- a/src/test/ui/issues/issue-22933-2.stderr
+++ b/src/test/ui/issues/issue-22933-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `PIE` found for type `Delicious` in the current scope
+error[E0599]: no variant or associated item named `PIE` found for enum `Delicious` in the current scope
   --> $DIR/issue-22933-2.rs:4:55
    |
 LL | enum Delicious {
diff --git a/src/test/ui/issues/issue-22933-3.rs b/src/test/ui/issues/issue-22933-3.rs
index 8518ed3..fbcce4b 100644
--- a/src/test/ui/issues/issue-22933-3.rs
+++ b/src/test/ui/issues/issue-22933-3.rs
@@ -1,4 +1,4 @@
 const FOO: [u32; u8::MIN as usize] = [];
-//~^ ERROR no associated item named `MIN` found for type `u8`
+//~^ ERROR no associated item named `MIN` found
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23173.rs b/src/test/ui/issues/issue-23173.rs
index 7c15598..92f4c54 100644
--- a/src/test/ui/issues/issue-23173.rs
+++ b/src/test/ui/issues/issue-23173.rs
@@ -7,7 +7,7 @@
 
 fn main() {
     use_token(&Token::Homura); //~ ERROR no variant or associated item named `Homura`
-    Struct::method(); //~ ERROR no function or associated item named `method` found for type
-    Struct::method; //~ ERROR no function or associated item named `method` found for type
-    Struct::Assoc; //~ ERROR no associated item named `Assoc` found for type `Struct` in
+    Struct::method(); //~ ERROR no function or associated item named `method` found
+    Struct::method; //~ ERROR no function or associated item named `method` found
+    Struct::Assoc; //~ ERROR no associated item named `Assoc` found
 }
diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr
index 699e411..89f70fd 100644
--- a/src/test/ui/issues/issue-23173.stderr
+++ b/src/test/ui/issues/issue-23173.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Homura` found for type `Token` in the current scope
+error[E0599]: no variant or associated item named `Homura` found for enum `Token` in the current scope
   --> $DIR/issue-23173.rs:9:23
    |
 LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
@@ -7,7 +7,7 @@
 LL |     use_token(&Token::Homura);
    |                       ^^^^^^ variant or associated item not found in `Token`
 
-error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:10:13
    |
 LL | struct Struct {
@@ -16,7 +16,7 @@
 LL |     Struct::method();
    |             ^^^^^^ function or associated item not found in `Struct`
 
-error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
+error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:11:13
    |
 LL | struct Struct {
@@ -25,7 +25,7 @@
 LL |     Struct::method;
    |             ^^^^^^ function or associated item not found in `Struct`
 
-error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope
+error[E0599]: no associated item named `Assoc` found for struct `Struct` in the current scope
   --> $DIR/issue-23173.rs:12:13
    |
 LL | struct Struct {
diff --git a/src/test/ui/issues/issue-23217.rs b/src/test/ui/issues/issue-23217.rs
index 157f20d..09f9ebc 100644
--- a/src/test/ui/issues/issue-23217.rs
+++ b/src/test/ui/issues/issue-23217.rs
@@ -1,5 +1,5 @@
 pub enum SomeEnum {
-    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found for type `SomeEnum`
+    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr
index 97100ed..a81b459 100644
--- a/src/test/ui/issues/issue-23217.stderr
+++ b/src/test/ui/issues/issue-23217.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `A` found for type `SomeEnum` in the current scope
+error[E0599]: no variant or associated item named `A` found for enum `SomeEnum` in the current scope
   --> $DIR/issue-23217.rs:2:19
    |
 LL | pub enum SomeEnum {
diff --git a/src/test/ui/issues/issue-23311.rs b/src/test/ui/issues/issue-23311.rs
index f275c63..62c9684 100644
--- a/src/test/ui/issues/issue-23311.rs
+++ b/src/test/ui/issues/issue-23311.rs
@@ -1,7 +1,6 @@
 // run-pass
-// Test that we do not ICE when pattern matching an array against a slice.
 
-#![feature(slice_patterns)]
+// Test that we do not ICE when pattern matching an array against a slice.
 
 fn main() {
     match "foo".as_bytes() {
diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr
index b0e729a..036c05f 100644
--- a/src/test/ui/issues/issue-24036.stderr
+++ b/src/test/ui/issues/issue-24036.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-24036.rs:3:9
    |
+LL |     let mut x = |c| c + 1;
+   |                 --------- the expected closure
 LL |     x = |c| c + 1;
    |         ^^^^^^^^^ expected closure, found a different closure
    |
diff --git a/src/test/ui/issues/issue-25385.rs b/src/test/ui/issues/issue-25385.rs
index adad6c3..ea042a6 100644
--- a/src/test/ui/issues/issue-25385.rs
+++ b/src/test/ui/issues/issue-25385.rs
@@ -1,6 +1,6 @@
 macro_rules! foo {
     ($e:expr) => { $e.foo() }
-    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+    //~^ ERROR no method named `foo` found
 }
 
 fn main() {
@@ -8,5 +8,5 @@
     foo!(a);
 
     foo!(1i32.foo());
-    //~^ ERROR no method named `foo` found for type `i32` in the current scope
+    //~^ ERROR no method named `foo` found
 }
diff --git a/src/test/ui/issues/issue-26619.rs b/src/test/ui/issues/issue-26619.rs
index 00e09f3..b9d34b0 100644
--- a/src/test/ui/issues/issue-26619.rs
+++ b/src/test/ui/issues/issue-26619.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 pub struct History<'a> { pub _s: &'a str }
 
 impl<'a> History<'a> {
diff --git a/src/test/ui/issues/issue-26619.stderr b/src/test/ui/issues/issue-26619.stderr
index d1157cd..1282fd7 100644
--- a/src/test/ui/issues/issue-26619.stderr
+++ b/src/test/ui/issues/issue-26619.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing function parameter
-  --> $DIR/issue-26619.rs:7:76
+  --> $DIR/issue-26619.rs:5:76
    |
 LL |         for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
    |                                                                  --------  ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
index 6d7c1b0..85d5d9c 100644
--- a/src/test/ui/issues/issue-26638.stderr
+++ b/src/test/ui/issues/issue-26638.stderr
@@ -2,9 +2,13 @@
   --> $DIR/issue-26638.rs:1:62
    |
 LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-   |                                                              ^ expected lifetime parameter
+   |                                                              ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL | fn parse_type<'lifetime>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'lifetime str { iter.next() }
+   |              ^^^^^^^^^^^                                                ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-26638.rs:4:40
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index c9ede03..aa720fd 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `C` in the current scope
+error[E0599]: no method named `clone` found for struct `C` in the current scope
   --> $DIR/issue-2823.rs:13:16
    |
 LL | struct C {
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
index e315317..77bc829 100644
--- a/src/test/ui/issues/issue-28344.stderr
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -4,7 +4,7 @@
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                 ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
 
-error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+error[E0599]: no function or associated item named `bitor` found for trait object `dyn std::ops::BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:4:25
    |
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
@@ -19,7 +19,7 @@
 LL |     let g = BitXor::bitor;
    |             ^^^^^^ help: specify the associated type: `BitXor<Output = Type>`
 
-error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
+error[E0599]: no function or associated item named `bitor` found for trait object `dyn std::ops::BitXor<_>` in the current scope
   --> $DIR/issue-28344.rs:8:21
    |
 LL |     let g = BitXor::bitor;
diff --git a/src/test/ui/issues/issue-28388-2.stderr b/src/test/ui/issues/issue-28388-2.stderr
index 7bbe0bc..58bd775 100644
--- a/src/test/ui/issues/issue-28388-2.stderr
+++ b/src/test/ui/issues/issue-28388-2.stderr
@@ -2,7 +2,13 @@
   --> $DIR/issue-28388-2.rs:7:8
    |
 LL | use m::n::{};
-   |        ^
+   |        ^ this module is private
+   |
+note: the module `n` is defined here
+  --> $DIR/issue-28388-2.rs:4:5
+   |
+LL |     mod n {}
+   |     ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28586.rs b/src/test/ui/issues/issue-28586.rs
index 4d286be..c543ef9 100644
--- a/src/test/ui/issues/issue-28586.rs
+++ b/src/test/ui/issues/issue-28586.rs
@@ -2,6 +2,6 @@
 
 pub trait Foo {}
 impl Foo for [u8; usize::BYTES] {}
-//~^ ERROR no associated item named `BYTES` found for type `usize`
+//~^ ERROR no associated item named `BYTES` found
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-28837.rs b/src/test/ui/issues/issue-28837.rs
index 438a4c5..f874b00 100644
--- a/src/test/ui/issues/issue-28837.rs
+++ b/src/test/ui/issues/issue-28837.rs
@@ -5,7 +5,7 @@
 
     a + a; //~ ERROR cannot add `A` to `A`
 
-    a - a; //~ ERROR cannot substract `A` from `A`
+    a - a; //~ ERROR cannot subtract `A` from `A`
 
     a * a; //~ ERROR cannot multiply `A` to `A`
 
diff --git a/src/test/ui/issues/issue-28837.stderr b/src/test/ui/issues/issue-28837.stderr
index 2ef571b..b63e168 100644
--- a/src/test/ui/issues/issue-28837.stderr
+++ b/src/test/ui/issues/issue-28837.stderr
@@ -8,7 +8,7 @@
    |
    = note: an implementation of `std::ops::Add` might be missing for `A`
 
-error[E0369]: cannot substract `A` from `A`
+error[E0369]: cannot subtract `A` from `A`
   --> $DIR/issue-28837.rs:8:7
    |
 LL |     a - a;
diff --git a/src/test/ui/issues/issue-28971.rs b/src/test/ui/issues/issue-28971.rs
index 6493565..f0a1e2d 100644
--- a/src/test/ui/issues/issue-28971.rs
+++ b/src/test/ui/issues/issue-28971.rs
@@ -5,7 +5,7 @@
     foo(|| {
         match Foo::Bar(1) {
             Foo::Baz(..) => (),
-            //~^ ERROR no variant or associated item named `Baz` found for type `Foo`
+            //~^ ERROR no variant or associated item named `Baz` found
             _ => (),
         }
     });
diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr
index 7411896..2736ee8 100644
--- a/src/test/ui/issues/issue-28971.stderr
+++ b/src/test/ui/issues/issue-28971.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no variant or associated item named `Baz` found for type `Foo` in the current scope
+error[E0599]: no variant or associated item named `Baz` found for enum `Foo` in the current scope
   --> $DIR/issue-28971.rs:7:18
    |
 LL | enum Foo {
diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/issues/issue-29124.rs
index 1cd3f84..dd27848 100644
--- a/src/test/ui/issues/issue-29124.rs
+++ b/src/test/ui/issues/issue-29124.rs
@@ -13,7 +13,7 @@
 
 fn main() {
     Obj::func.x();
-    //~^ ERROR no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+    //~^ ERROR no method named `x` found
     func.x();
-    //~^ ERROR no method named `x` found for type `fn() -> Ret {func}` in the current scope
+    //~^ ERROR no method named `x` found
 }
diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr
index c537c61..42d89cd 100644
--- a/src/test/ui/issues/issue-29124.stderr
+++ b/src/test/ui/issues/issue-29124.stderr
@@ -1,18 +1,18 @@
-error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope
+error[E0599]: no method named `x` found for fn item `fn() -> Ret {Obj::func}` in the current scope
   --> $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
+   = note: `Obj::func` is a function, perhaps you wish to call it
 
-error[E0599]: no method named `x` found for type `fn() -> Ret {func}` in the current scope
+error[E0599]: no method named `x` found for fn item `fn() -> Ret {func}` in the current scope
   --> $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
+   = note: `func` is a function, perhaps you wish to call it
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-29161.stderr b/src/test/ui/issues/issue-29161.stderr
index d30fd28..1bfa211 100644
--- a/src/test/ui/issues/issue-29161.stderr
+++ b/src/test/ui/issues/issue-29161.stderr
@@ -8,7 +8,13 @@
   --> $DIR/issue-29161.rs:13:8
    |
 LL |     a::A::default();
-   |        ^
+   |        ^ this struct is private
+   |
+note: the struct `A` is defined here
+  --> $DIR/issue-29161.rs:2:5
+   |
+LL |     struct A;
+   |     ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-30123.rs b/src/test/ui/issues/issue-30123.rs
index 4fc32e0..705355d 100644
--- a/src/test/ui/issues/issue-30123.rs
+++ b/src/test/ui/issues/issue-30123.rs
@@ -5,5 +5,5 @@
 
 fn main() {
     let ug = Graph::<i32, i32>::new_undirected();
-    //~^ ERROR no function or associated item named `new_undirected` found for type
+    //~^ ERROR no function or associated item named `new_undirected` found
 }
diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr
index 32bbd4d..bc67316 100644
--- a/src/test/ui/issues/issue-30123.stderr
+++ b/src/test/ui/issues/issue-30123.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new_undirected` found for type `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
   --> $DIR/issue-30123.rs:7:33
    |
 LL |     let ug = Graph::<i32, i32>::new_undirected();
diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr
index c53129b..c940227 100644
--- a/src/test/ui/issues/issue-30255.stderr
+++ b/src/test/ui/issues/issue-30255.stderr
@@ -2,25 +2,37 @@
   --> $DIR/issue-30255.rs:9:24
    |
 LL | fn f(a: &S, b: i32) -> &i32 {
-   |                        ^ expected lifetime parameter
+   |                        ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL | fn f<'lifetime>(a: &S, b: i32) -> &'lifetime i32 {
+   |     ^^^^^^^^^^^                   ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:14:34
    |
 LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
-   |                                  ^ expected lifetime parameter
+   |                                  ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn g<'lifetime>(a: &S, b: bool, c: &i32) -> &'lifetime i32 {
+   |     ^^^^^^^^^^^                             ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:19:44
    |
 LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
-   |                                            ^ expected lifetime parameter
+   |                                            ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn h<'lifetime>(a: &bool, b: bool, c: &S, d: &i32) -> &'lifetime i32 {
+   |     ^^^^^^^^^^^                                       ^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-30302.stderr b/src/test/ui/issues/issue-30302.stderr
index d762d6f..ac1b523 100644
--- a/src/test/ui/issues/issue-30302.stderr
+++ b/src/test/ui/issues/issue-30302.stderr
@@ -3,6 +3,8 @@
    |
 LL |         Nil => true,
    |         ^^^ help: to match on the variant, qualify the path: `Stack::Nil`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 error: unreachable pattern
   --> $DIR/issue-30302.rs:15:9
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index 38cf3c4..a614b96 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -7,7 +7,7 @@
    = note:   expected type `u8`
            found reference `&_`
 
-error[E0599]: no method named `collect` found for type `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
+error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
   --> $DIR/issue-31173.rs:14:10
    |
 LL |         .collect();
diff --git a/src/test/ui/issues/issue-32963.rs b/src/test/ui/issues/issue-32963.rs
index ee09906..3e6cf44 100644
--- a/src/test/ui/issues/issue-32963.rs
+++ b/src/test/ui/issues/issue-32963.rs
@@ -7,5 +7,6 @@
 fn main() {
     size_of_copy::<dyn Misc + Copy>();
     //~^ ERROR only auto traits can be used as additional traits in a trait object
+    //~| ERROR only auto traits can be used as additional traits in a trait object
     //~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied
 }
diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr
index e3564e8..450c37f 100644
--- a/src/test/ui/issues/issue-32963.stderr
+++ b/src/test/ui/issues/issue-32963.stderr
@@ -9,6 +9,17 @@
    |                        first non-auto trait
    |                        trait alias used in trait object type (first use)
 
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/issue-32963.rs:8:31
+   |
+LL |     size_of_copy::<dyn Misc + Copy>();
+   |                        ----   ^^^^
+   |                        |      |
+   |                        |      additional non-auto trait
+   |                        |      trait alias used in trait object type (additional use)
+   |                        first non-auto trait
+   |                        trait alias used in trait object type (first use)
+
 error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
   --> $DIR/issue-32963.rs:8:5
    |
@@ -18,7 +29,7 @@
 LL |     size_of_copy::<dyn Misc + Copy>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0225, E0277.
 For more information about an error, try `rustc --explain E0225`.
diff --git a/src/test/ui/issues/issue-33571.rs b/src/test/ui/issues/issue-33571.rs
index 147fb3f..2713f47 100644
--- a/src/test/ui/issues/issue-33571.rs
+++ b/src/test/ui/issues/issue-33571.rs
@@ -1,5 +1,6 @@
 #[derive(Clone,
          Sync, //~ ERROR cannot find derive macro `Sync` in this scope
+               //~| ERROR cannot find derive macro `Sync` in this scope
          Copy)]
 enum Foo {}
 
diff --git a/src/test/ui/issues/issue-33571.stderr b/src/test/ui/issues/issue-33571.stderr
index 78e7202..2a9ba5b 100644
--- a/src/test/ui/issues/issue-33571.stderr
+++ b/src/test/ui/issues/issue-33571.stderr
@@ -10,5 +10,17 @@
 LL |          Sync,
    |          ^^^^
 
-error: aborting due to previous error
+error: cannot find derive macro `Sync` in this scope
+  --> $DIR/issue-33571.rs:2:10
+   |
+LL |          Sync,
+   |          ^^^^
+   |
+note: unsafe traits like `Sync` should be implemented explicitly
+  --> $DIR/issue-33571.rs:2:10
+   |
+LL |          Sync,
+   |          ^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-33575.rs b/src/test/ui/issues/issue-33575.rs
index 09c4994..de544af 100644
--- a/src/test/ui/issues/issue-33575.rs
+++ b/src/test/ui/issues/issue-33575.rs
@@ -1,4 +1,4 @@
 fn main() {
-    let baz = ().foo(); //~ ERROR no method named `foo` found for type `()` in the current scope
+    let baz = ().foo(); //~ ERROR no method named `foo` found
     <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
 }
diff --git a/src/test/ui/issues/issue-33575.stderr b/src/test/ui/issues/issue-33575.stderr
index e6b74d2..bbd8042 100644
--- a/src/test/ui/issues/issue-33575.stderr
+++ b/src/test/ui/issues/issue-33575.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `()` in the current scope
+error[E0599]: no method named `foo` found for unit type `()` in the current scope
   --> $DIR/issue-33575.rs:2:18
    |
 LL |     let baz = ().foo();
diff --git a/src/test/ui/issues/issue-34209.rs b/src/test/ui/issues/issue-34209.rs
index fc2c367..632ddb9 100644
--- a/src/test/ui/issues/issue-34209.rs
+++ b/src/test/ui/issues/issue-34209.rs
@@ -4,7 +4,7 @@
 
 fn bug(l: S) {
     match l {
-        S::B {} => {}, //~ ERROR no variant `B` in enum `S`
+        S::B {} => {}, //~ ERROR no variant named `B` found for enum `S`
     }
 }
 
diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr
index 194bb2b..f9a25b6 100644
--- a/src/test/ui/issues/issue-34209.stderr
+++ b/src/test/ui/issues/issue-34209.stderr
@@ -1,4 +1,4 @@
-error: no variant `B` in enum `S`
+error[E0599]: no variant named `B` found for enum `S`
   --> $DIR/issue-34209.rs:7:12
    |
 LL | enum S {
@@ -9,3 +9,4 @@
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-34229.rs b/src/test/ui/issues/issue-34229.rs
index 13e627a..625fcb0 100644
--- a/src/test/ui/issues/issue-34229.rs
+++ b/src/test/ui/issues/issue-34229.rs
@@ -1,5 +1,9 @@
 #[derive(PartialEq)] struct Comparable;
 #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
 //~^ ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
+//~| ERROR can't compare `Comparable`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr
index c57f80c..9e17348 100644
--- a/src/test/ui/issues/issue-34229.stderr
+++ b/src/test/ui/issues/issue-34229.stderr
@@ -7,6 +7,42 @@
    = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
-error: aborting due to previous error
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `Comparable` with `Comparable`
+  --> $DIR/issue-34229.rs:2:46
+   |
+LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable);
+   |                                              ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `Comparable`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs
index e34b5c9..afe4d42 100644
--- a/src/test/ui/issues/issue-34334.rs
+++ b/src/test/ui/issues/issue-34334.rs
@@ -7,5 +7,5 @@
     //~| ERROR expected expression, found reserved identifier `_`
     //~| ERROR expected expression, found reserved identifier `_`
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-    //~^ ERROR no method named `iter` found for type `()` in the current scope
+    //~^ ERROR no method named `iter` found
 }
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 3055e31..c52ea4e 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -43,7 +43,7 @@
    |             |
    |             cannot assign to this expression
 
-error[E0599]: no method named `iter` found for type `()` in the current scope
+error[E0599]: no method named `iter` found for unit type `()` in the current scope
   --> $DIR/issue-34334.rs:9:36
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr
index b381203..a998f95 100644
--- a/src/test/ui/issues/issue-35677.stderr
+++ b/src/test/ui/issues/issue-35677.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `is_subset` found for type `&std::collections::HashSet<T>` in the current scope
+error[E0599]: no method named `is_subset` found for reference `&std::collections::HashSet<T>` in the current scope
   --> $DIR/issue-35677.rs:4:10
    |
 LL |     this.is_subset(other)
diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs
index 1102f3c..58f44f4 100644
--- a/src/test/ui/issues/issue-36617.rs
+++ b/src/test/ui/issues/issue-36617.rs
@@ -1,4 +1,5 @@
 #![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
                  //~| ERROR cannot determine resolution for the derive macro `Copy`
+                 //~| ERROR cannot determine resolution for the derive macro `Copy`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr
index b5db98f..98b41b0 100644
--- a/src/test/ui/issues/issue-36617.stderr
+++ b/src/test/ui/issues/issue-36617.stderr
@@ -12,5 +12,13 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 2 previous errors
+error: cannot determine resolution for the derive macro `Copy`
+  --> $DIR/issue-36617.rs:1:11
+   |
+LL | #![derive(Copy)]
+   |           ^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-3707.rs b/src/test/ui/issues/issue-3707.rs
index 844a2dc..0817c51 100644
--- a/src/test/ui/issues/issue-3707.rs
+++ b/src/test/ui/issues/issue-3707.rs
@@ -7,7 +7,7 @@
         return 1+1 == 2
     }
     pub fn chirp(&self) {
-        self.boom(); //~ ERROR no method named `boom` found for type `&Obj` in the current scope
+        self.boom(); //~ ERROR no method named `boom` found
     }
 }
 
diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr
index b98bc57..6ca2dee 100644
--- a/src/test/ui/issues/issue-3707.stderr
+++ b/src/test/ui/issues/issue-3707.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `boom` found for type `&Obj` in the current scope
+error[E0599]: no method named `boom` found for reference `&Obj` in the current scope
   --> $DIR/issue-3707.rs:10:14
    |
 LL |         self.boom();
diff --git a/src/test/ui/issues/issue-37598.rs b/src/test/ui/issues/issue-37598.rs
index 31b3aba..458e999 100644
--- a/src/test/ui/issues/issue-37598.rs
+++ b/src/test/ui/issues/issue-37598.rs
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn check(list: &[u8]) {
     match list {
diff --git a/src/test/ui/issues/issue-38591.rs b/src/test/ui/issues/issue-38591.rs
deleted file mode 100644
index 2f594b4..0000000
--- a/src/test/ui/issues/issue-38591.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-struct S<T> {
-    t : T,
-    s : Box<S<fn(u : T)>>
-}
-
-fn f(x : S<u32>) {}
-
-fn main () {}
diff --git a/src/test/ui/issues/issue-38857.rs b/src/test/ui/issues/issue-38857.rs
index 81d881c..c0695f8 100644
--- a/src/test/ui/issues/issue-38857.rs
+++ b/src/test/ui/issues/issue-38857.rs
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 fn main() {
     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
     //~^ ERROR failed to resolve: could not find `imp` in `sys` [E0433]
diff --git a/src/test/ui/issues/issue-38857.stderr b/src/test/ui/issues/issue-38857.stderr
index 5762e3d..ba0f133 100644
--- a/src/test/ui/issues/issue-38857.stderr
+++ b/src/test/ui/issues/issue-38857.stderr
@@ -1,14 +1,20 @@
 error[E0433]: failed to resolve: could not find `imp` in `sys`
-  --> $DIR/issue-38857.rs:2:23
+  --> $DIR/issue-38857.rs:7:23
    |
 LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
    |                       ^^^ could not find `imp` in `sys`
 
 error[E0603]: module `sys` is private
-  --> $DIR/issue-38857.rs:2:18
+  --> $DIR/issue-38857.rs:7:18
    |
 LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `sys` is defined here
+  --> $SRC_DIR/libstd/lib.rs:LL:COL
+   |
+LL | mod sys;
+   | ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-38919.rs b/src/test/ui/issues/issue-38919.rs
index 60a8793..3d28f19 100644
--- a/src/test/ui/issues/issue-38919.rs
+++ b/src/test/ui/issues/issue-38919.rs
@@ -1,5 +1,5 @@
 fn foo<T: Iterator>() {
-    T::Item; //~ ERROR no associated item named `Item` found for type `T` in the current scope
+    T::Item; //~ ERROR no associated item named `Item` found
 }
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr
index 603d42c..0022065 100644
--- a/src/test/ui/issues/issue-38919.stderr
+++ b/src/test/ui/issues/issue-38919.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `Item` found for type `T` in the current scope
+error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope
   --> $DIR/issue-38919.rs:2:8
    |
 LL |     T::Item;
diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr
index 8b173e1..2f6e676 100644
--- a/src/test/ui/issues/issue-39175.stderr
+++ b/src/test/ui/issues/issue-39175.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `exec` found for type `&mut std::process::Command` in the current scope
+error[E0599]: no method named `exec` found for mutable reference `&mut std::process::Command` in the current scope
   --> $DIR/issue-39175.rs:15:39
    |
 LL |     Command::new("echo").arg("hello").exec();
diff --git a/src/test/ui/issues/issue-39559.rs b/src/test/ui/issues/issue-39559.rs
index 5af48ca..3a75956 100644
--- a/src/test/ui/issues/issue-39559.rs
+++ b/src/test/ui/issues/issue-39559.rs
@@ -12,7 +12,7 @@
 
 pub struct Vector<T, D: Dim> {
     entries: [T; D::dim()],
-    //~^ ERROR no function or associated item named `dim` found for type `D` in the current scope
+    //~^ ERROR no function or associated item named `dim` found
     _dummy: D,
 }
 
diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr
index b945b5e..0554b23 100644
--- a/src/test/ui/issues/issue-39559.stderr
+++ b/src/test/ui/issues/issue-39559.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `dim` found for type `D` in the current scope
+error[E0599]: no function or associated item named `dim` found for type parameter `D` in the current scope
   --> $DIR/issue-39559.rs:14:21
    |
 LL |     entries: [T; D::dim()],
diff --git a/src/test/ui/issues/issue-39720.rs b/src/test/ui/issues/issue-39720.rs
index 1a4775f..8cf841f 100644
--- a/src/test/ui/issues/issue-39720.rs
+++ b/src/test/ui/issues/issue-39720.rs
@@ -1,26 +1,22 @@
 // run-pass
-#![allow(non_snake_case)]
-
 // ignore-emscripten FIXME(#45351)
 
 #![feature(repr_simd, platform_intrinsics)]
 
-#[repr(C)] //~ WARNING conflicting representation hints
 #[repr(simd)]
 #[derive(Copy, Clone, Debug)]
-pub struct char3(pub i8, pub i8, pub i8);
+pub struct Char3(pub i8, pub i8, pub i8);
 
-#[repr(C)]  //~ WARNING conflicting representation hints
 #[repr(simd)]
 #[derive(Copy, Clone, Debug)]
-pub struct short3(pub i16, pub i16, pub i16);
+pub struct Short3(pub i16, pub i16, pub i16);
 
 extern "platform-intrinsic" {
     fn simd_cast<T, U>(x: T) -> U;
 }
 
 fn main() {
-    let cast: short3 = unsafe { simd_cast(char3(10, -3, -9)) };
+    let cast: Short3 = unsafe { simd_cast(Char3(10, -3, -9)) };
 
     println!("{:?}", cast);
 }
diff --git a/src/test/ui/issues/issue-39720.stderr b/src/test/ui/issues/issue-39720.stderr
deleted file mode 100644
index 8121ed2..0000000
--- a/src/test/ui/issues/issue-39720.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-39720.rs:8:8
-   |
-LL | #[repr(C)]
-   |        ^
-LL | #[repr(simd)]
-   |        ^^^^
-
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-39720.rs:13:8
-   |
-LL | #[repr(C)]
-   |        ^
-LL | #[repr(simd)]
-   |        ^^^^
-
diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/issues/issue-3973.rs
index 4e00915..a5ed5b8 100644
--- a/src/test/ui/issues/issue-3973.rs
+++ b/src/test/ui/issues/issue-3973.rs
@@ -20,6 +20,6 @@
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    //~^ ERROR no function or associated item named `new` found for type `Point`
+    //~^ ERROR no function or associated item named `new` found for struct `Point`
     println!("{}", p.to_string());
 }
diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr
index ee07a41..63282e8 100644
--- a/src/test/ui/issues/issue-3973.stderr
+++ b/src/test/ui/issues/issue-3973.stderr
@@ -7,7 +7,7 @@
 LL | |     }
    | |_____^ not a member of trait `ToString_`
 
-error[E0599]: no function or associated item named `new` found for type `Point` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
   --> $DIR/issue-3973.rs:22:20
    |
 LL | struct Point {
diff --git a/src/test/ui/issues/issue-3993.stderr b/src/test/ui/issues/issue-3993.stderr
index ce594a3..3fa8ed4 100644
--- a/src/test/ui/issues/issue-3993.stderr
+++ b/src/test/ui/issues/issue-3993.stderr
@@ -2,7 +2,13 @@
   --> $DIR/issue-3993.rs:1:10
    |
 LL | use zoo::fly;
-   |          ^^^
+   |          ^^^ this function is private
+   |
+note: the function `fly` is defined here
+  --> $DIR/issue-3993.rs:4:5
+   |
+LL |     fn fly() {}
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs
index 60fdf7c..5b95a73 100644
--- a/src/test/ui/issues/issue-41255.rs
+++ b/src/test/ui/issues/issue-41255.rs
@@ -1,6 +1,7 @@
 // Matching against float literals should result in a linter error
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 #![allow(unused)]
 #![forbid(illegal_floating_point_literal_pattern)]
 
@@ -12,23 +13,53 @@
                    //~| ERROR floating-point types cannot be used in patterns
                    //~| WARNING this was previously accepted by the compiler but is being
         5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
+                      //~| ERROR floating-point types cannot be used in patterns
+                      //~| WARNING hard error
                       //~| WARNING hard error
         -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                    //~| ERROR floating-point types cannot be used in patterns
+                    //~| WARNING hard error
                     //~| WARNING hard error
         1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
                            //~| WARNING hard error
                            //~| ERROR floating-point types cannot be used in patterns
                            //~| WARNING hard error
+                           //~| ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
+                           //~| ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
         39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                             //~| WARNING hard error
                              //~| ERROR floating-point types cannot be used in patterns
                              //~| WARNING hard error
+                             //~| ERROR floating-point types cannot be used in patterns
+                             //~| ERROR floating-point types cannot be used in patterns
+                             //~| WARNING hard error
+                             //~| WARNING hard error
+                             //~| WARNING hard error
+
+        ..71.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
+        ..=72.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
+        71.0.. => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| ERROR floating-point types cannot be used in patterns
+        //~| WARNING hard error
+        //~| WARNING this was previously accepted by the compiler
         _ => {},
     };
     let y = 5.0;
     // Same for tuples
     match (x, 5) {
         (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
+                         //~| ERROR floating-point types cannot be used
+                         //~| WARNING hard error
                          //~| WARNING hard error
         _ => {},
     }
@@ -36,6 +67,8 @@
     struct Foo { x: f32 };
     match (Foo { x }) {
         Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
+                              //~| ERROR floating-point types cannot be used
+                              //~| WARNING hard error
                               //~| WARNING hard error
         _ => {},
     }
diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr
index c334742..1ff5815 100644
--- a/src/test/ui/issues/issue-41255.stderr
+++ b/src/test/ui/issues/issue-41255.stderr
@@ -1,11 +1,11 @@
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:10:9
+  --> $DIR/issue-41255.rs:11:9
    |
 LL |         5.0 => {},
    |         ^^^
    |
 note: lint level defined here
-  --> $DIR/issue-41255.rs:5:11
+  --> $DIR/issue-41255.rs:6:11
    |
 LL | #![forbid(illegal_floating_point_literal_pattern)]
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:14:9
+  --> $DIR/issue-41255.rs:15:9
    |
 LL |         5.0f32 => {},
    |         ^^^^^^
@@ -22,7 +22,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:16:10
+  --> $DIR/issue-41255.rs:19:10
    |
 LL |         -5.0 => {},
    |          ^^^
@@ -31,7 +31,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:18:9
+  --> $DIR/issue-41255.rs:23:9
    |
 LL |         1.0 .. 33.0 => {},
    |         ^^^
@@ -40,7 +40,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:18:16
+  --> $DIR/issue-41255.rs:23:16
    |
 LL |         1.0 .. 33.0 => {},
    |                ^^^^
@@ -49,7 +49,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:9
+  --> $DIR/issue-41255.rs:31:9
    |
 LL |         39.0 ..= 70.0 => {},
    |         ^^^^
@@ -58,7 +58,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:22:18
+  --> $DIR/issue-41255.rs:31:18
    |
 LL |         39.0 ..= 70.0 => {},
    |                  ^^^^
@@ -67,7 +67,34 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:31:10
+  --> $DIR/issue-41255.rs:40:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:45:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:50:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:60:10
    |
 LL |         (3.14, 1) => {},
    |          ^^^^
@@ -76,7 +103,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:38:18
+  --> $DIR/issue-41255.rs:69:18
    |
 LL |         Foo { x: 2.0 } => {},
    |                  ^^^
@@ -85,7 +112,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:10:9
+  --> $DIR/issue-41255.rs:11:9
    |
 LL |         5.0 => {},
    |         ^^^
@@ -93,5 +120,104 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to 10 previous errors
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:15:9
+   |
+LL |         5.0f32 => {},
+   |         ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:19:10
+   |
+LL |         -5.0 => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:23:9
+   |
+LL |         1.0 .. 33.0 => {},
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:23:16
+   |
+LL |         1.0 .. 33.0 => {},
+   |                ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:31:9
+   |
+LL |         39.0 ..= 70.0 => {},
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:31:18
+   |
+LL |         39.0 ..= 70.0 => {},
+   |                  ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:40:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:45:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:50:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:60:10
+   |
+LL |         (3.14, 1) => {},
+   |          ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:69:18
+   |
+LL |         Foo { x: 2.0 } => {},
+   |                  ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/issues/issue-41880.rs b/src/test/ui/issues/issue-41880.rs
index 16facc5..10cde21 100644
--- a/src/test/ui/issues/issue-41880.rs
+++ b/src/test/ui/issues/issue-41880.rs
@@ -25,5 +25,5 @@
 fn main() {
     let a = iterate(0, |x| x+1);
     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-    //~^ ERROR no method named `iter` found for type `Iterate<{integer}
+    //~^ ERROR no method named `iter` found
 }
diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr
index 0e1d55c..09d5594 100644
--- a/src/test/ui/issues/issue-41880.stderr
+++ b/src/test/ui/issues/issue-41880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `iter` found for type `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
+error[E0599]: no method named `iter` found for struct `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` in the current scope
   --> $DIR/issue-41880.rs:27:24
    |
 LL | pub struct Iterate<T, F> {
diff --git a/src/test/ui/issues/issue-42880.stderr b/src/test/ui/issues/issue-42880.stderr
index 763bb9a..82cdc20 100644
--- a/src/test/ui/issues/issue-42880.stderr
+++ b/src/test/ui/issues/issue-42880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no associated item named `String` found for type `std::string::String` in the current scope
+error[E0599]: no associated item named `String` found for struct `std::string::String` in the current scope
   --> $DIR/issue-42880.rs:4:22
    |
 LL |     let f = |&Value::String(_)| ();
diff --git a/src/test/ui/issues/issue-43105.rs b/src/test/ui/issues/issue-43105.rs
index f61b65b..231af76 100644
--- a/src/test/ui/issues/issue-43105.rs
+++ b/src/test/ui/issues/issue-43105.rs
@@ -8,6 +8,7 @@
     match 1 {
         NUM => unimplemented!(),
         //~^ ERROR could not evaluate constant pattern
+        //~| ERROR could not evaluate constant pattern
         _ => unimplemented!(),
     }
 }
diff --git a/src/test/ui/issues/issue-43105.stderr b/src/test/ui/issues/issue-43105.stderr
index e3609c5..1a7b67b 100644
--- a/src/test/ui/issues/issue-43105.stderr
+++ b/src/test/ui/issues/issue-43105.stderr
@@ -20,6 +20,12 @@
 LL |         NUM => unimplemented!(),
    |         ^^^
 
-error: aborting due to 3 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/issue-43105.rs:9:9
+   |
+LL |         NUM => unimplemented!(),
+   |         ^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/issues/issue-43189.rs
index f4f4dce..ce667a5 100644
--- a/src/test/ui/issues/issue-43189.rs
+++ b/src/test/ui/issues/issue-43189.rs
@@ -8,5 +8,5 @@
 extern crate xcrate_issue_43189_b;
 fn main() {
     ().a();
-    //~^ ERROR no method named `a` found for type `()` in the current scope [E0599]
+    //~^ ERROR no method named `a` found
 }
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
index 4dae6c1..3f63cb8e7 100644
--- a/src/test/ui/issues/issue-43189.stderr
+++ b/src/test/ui/issues/issue-43189.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `a` found for type `()` in the current scope
+error[E0599]: no method named `a` found for unit type `()` in the current scope
   --> $DIR/issue-43189.rs:10:8
    |
 LL |     ().a();
diff --git a/src/test/ui/issues/issue-45730.stderr b/src/test/ui/issues/issue-45730.stderr
index 3c400d6..d4ddba5 100644
--- a/src/test/ui/issues/issue-45730.stderr
+++ b/src/test/ui/issues/issue-45730.stderr
@@ -6,7 +6,7 @@
    |                            |
    |                            help: consider giving more type information
    |
-   = note: The type information given here is insufficient to check whether the pointer cast is valid
+   = note: the type information given here is insufficient to check whether the pointer cast is valid
 
 error[E0641]: cannot cast to a pointer of an unknown kind
   --> $DIR/issue-45730.rs:5:23
@@ -16,7 +16,7 @@
    |                            |
    |                            help: consider giving more type information
    |
-   = note: The type information given here is insufficient to check whether the pointer cast is valid
+   = note: the type information given here is insufficient to check whether the pointer cast is valid
 
 error[E0641]: cannot cast to a pointer of an unknown kind
   --> $DIR/issue-45730.rs:8:13
@@ -26,7 +26,7 @@
    |                                            |
    |                                            help: consider giving more type information
    |
-   = note: The type information given here is insufficient to check whether the pointer cast is valid
+   = note: the type information given here is insufficient to check whether the pointer cast is valid
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs
index 8b1343b..7c8bf29 100644
--- a/src/test/ui/issues/issue-46101.rs
+++ b/src/test/ui/issues/issue-46101.rs
@@ -1,6 +1,7 @@
 #![feature(use_extern_macros)]
 trait Foo {}
 #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
+                         //~| 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 9c88d3b..2ffa152 100644
--- a/src/test/ui/issues/issue-46101.stderr
+++ b/src/test/ui/issues/issue-46101.stderr
@@ -4,6 +4,12 @@
 LL | #[derive(Foo::Anything)]
    |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: partially resolved path in a derive macro
+  --> $DIR/issue-46101.rs:3:10
+   |
+LL | #[derive(Foo::Anything)]
+   |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-47094.rs b/src/test/ui/issues/issue-47094.rs
index 97da984..3258ee9 100644
--- a/src/test/ui/issues/issue-47094.rs
+++ b/src/test/ui/issues/issue-47094.rs
@@ -1,12 +1,10 @@
-// check-pass
-
-#[repr(C,u8)] //~ WARNING conflicting representation hints
+#[repr(C, u8)] //~ ERROR conflicting representation hints
 enum Foo {
     A,
     B,
 }
 
-#[repr(C)] //~ WARNING conflicting representation hints
+#[repr(C)] //~ ERROR conflicting representation hints
 #[repr(u8)]
 enum Bar {
     A,
diff --git a/src/test/ui/issues/issue-47094.stderr b/src/test/ui/issues/issue-47094.stderr
index 16bcec0..c807f64 100644
--- a/src/test/ui/issues/issue-47094.stderr
+++ b/src/test/ui/issues/issue-47094.stderr
@@ -1,14 +1,17 @@
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-47094.rs:3:8
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:1:8
    |
-LL | #[repr(C,u8)]
-   |        ^ ^^
+LL | #[repr(C, u8)]
+   |        ^  ^^
 
-warning[E0566]: conflicting representation hints
-  --> $DIR/issue-47094.rs:9:8
+error[E0566]: conflicting representation hints
+  --> $DIR/issue-47094.rs:7:8
    |
 LL | #[repr(C)]
    |        ^
 LL | #[repr(u8)]
    |        ^^
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0566`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
index 24c6142..5b6b8f8 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _result = &Some(42).as_deref();
-//~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>`
+//~^ ERROR no method named `as_deref` found for enum `std::option::Option<{integer}>`
 }
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
index 0eb7bf0..f91f6e8 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope
+error[E0599]: no method named `as_deref` found for enum `std::option::Option<{integer}>` in the current scope
   --> $DIR/option-as_deref.rs:2:29
    |
 LL |     let _result = &Some(42).as_deref();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
index 67ad73f..c5fe6ea 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _result = &mut Some(42).as_deref_mut();
-//~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>`
+//~^ ERROR no method named `as_deref_mut` found for enum `std::option::Option<{integer}>`
 }
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 845ddb5..5832363 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
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope
+error[E0599]: no method named `as_deref_mut` found for enum `std::option::Option<{integer}>` in the current scope
   --> $DIR/option-as_deref_mut.rs:2:33
    |
 LL |     let _result = &mut Some(42).as_deref_mut();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
index 5e01674..fae11fe 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref.rs:4:27
    |
 LL |     let _result = &Ok(42).as_deref();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
index 6dc13da..1d98361 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
@@ -1,8 +1,8 @@
-error[E0599]: no method named `as_deref_err` found for type `std::result::Result<_, {integer}>` in the current scope
+error[E0599]: no method named `as_deref_err` found for enum `std::result::Result<_, {integer}>` in the current scope
   --> $DIR/result-as_deref_err.rs:4:28
    |
 LL |     let _result = &Err(41).as_deref_err();
-   |                            ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_ok`
+   |                            ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::Deref`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
index f21e973..2c6231f 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `as_deref_mut` found for type `std::result::Result<{integer}, _>` in the current scope
+error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result<{integer}, _>` in the current scope
   --> $DIR/result-as_deref_mut.rs:4:31
    |
 LL |     let _result = &mut Ok(42).as_deref_mut();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
index 44c0c95..950a050 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
@@ -1,8 +1,8 @@
-error[E0599]: no method named `as_deref_mut_err` found for type `std::result::Result<_, {integer}>` in the current scope
+error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Result<_, {integer}>` in the current scope
   --> $DIR/result-as_deref_mut_err.rs:4:32
    |
 LL |     let _result = &mut Err(41).as_deref_mut_err();
-   |                                ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_ok`
+   |                                ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::DerefMut`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs
deleted file mode 100644
index 54b695a..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(inner_deref)]
-
-fn main() {
-    let _result = &mut Ok(42).as_deref_mut_ok();
-//~^ ERROR no method named `as_deref_mut_ok` found
-}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
deleted file mode 100644
index b8369c9..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0599]: no method named `as_deref_mut_ok` found for type `std::result::Result<{integer}, _>` in the current scope
-  --> $DIR/result-as_deref_mut_ok.rs:4:31
-   |
-LL |     let _result = &mut Ok(42).as_deref_mut_ok();
-   |                               ^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_err`
-   |
-   = note: the method `as_deref_mut_ok` exists but the following trait bounds were not satisfied:
-           `{integer} : std::ops::DerefMut`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs
deleted file mode 100644
index ebb0500..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(inner_deref)]
-
-fn main() {
-    let _result = &Ok(42).as_deref_ok();
-//~^ ERROR no method named `as_deref_ok` found
-}
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
deleted file mode 100644
index b26705a..0000000
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0599]: no method named `as_deref_ok` found for type `std::result::Result<{integer}, _>` in the current scope
-  --> $DIR/result-as_deref_ok.rs:4:27
-   |
-LL |     let _result = &Ok(42).as_deref_ok();
-   |                           ^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err`
-   |
-   = note: the method `as_deref_ok` exists but the following trait bounds were not satisfied:
-           `{integer} : std::ops::Deref`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/issues/issue-50480.rs
index 31dbb75..deb6387 100644
--- a/src/test/ui/issues/issue-50480.rs
+++ b/src/test/ui/issues/issue-50480.rs
@@ -2,6 +2,7 @@
 //~^ ERROR the trait `Copy` may not be implemented for this type
 struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
 //~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `NotDefined` in this scope
 //~| ERROR `i32` is not an iterator
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/issues/issue-50480.stderr
index 9022bfa..2b92664 100644
--- a/src/test/ui/issues/issue-50480.stderr
+++ b/src/test/ui/issues/issue-50480.stderr
@@ -4,6 +4,12 @@
 LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |            ^^^^^^^^^^ not found in this scope
 
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:12
+   |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |            ^^^^^^^^^^ not found in this scope
+
 error[E0277]: `i32` is not an iterator
   --> $DIR/issue-50480.rs:3:24
    |
@@ -24,7 +30,7 @@
    |                                                 |
    |                                                 this field does not implement `Copy`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0204, E0277, E0412.
 For more information about an error, try `rustc --explain E0204`.
diff --git a/src/test/ui/issues/issue-5153.rs b/src/test/ui/issues/issue-5153.rs
index e673766..5bf0579 100644
--- a/src/test/ui/issues/issue-5153.rs
+++ b/src/test/ui/issues/issue-5153.rs
@@ -8,5 +8,5 @@
 
 fn main() {
     (&5isize as &dyn Foo).foo();
-    //~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
+    //~^ ERROR: no method named `foo` found for reference `&dyn Foo` in the current scope
 }
diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr
index 5034e6d..4680c8b 100644
--- a/src/test/ui/issues/issue-5153.stderr
+++ b/src/test/ui/issues/issue-5153.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&dyn Foo` in the current scope
+error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope
   --> $DIR/issue-5153.rs:10:27
    |
 LL |     (&5isize as &dyn Foo).foo();
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
index c69145c..502825e 100644
--- a/src/test/ui/issues/issue-52060.stderr
+++ b/src/test/ui/issues/issue-52060.stderr
@@ -1,8 +1,10 @@
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0013]: constants cannot refer to statics
   --> $DIR/issue-52060.rs:4:26
    |
 LL | static B: [u32; 1] = [0; A.len()];
    |                          ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-52060.rs:4:26
diff --git a/src/test/ui/issues/issue-53251.rs b/src/test/ui/issues/issue-53251.rs
index 0751b0a..b5d5514 100644
--- a/src/test/ui/issues/issue-53251.rs
+++ b/src/test/ui/issues/issue-53251.rs
@@ -10,6 +10,7 @@
             fn $n() {
                 S::f::<i64>();
                 //~^ ERROR wrong number of type arguments
+                //~| ERROR wrong number of type arguments
             }
         )*
     }
diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr
index 9fbffaf..21e4157 100644
--- a/src/test/ui/issues/issue-53251.stderr
+++ b/src/test/ui/issues/issue-53251.stderr
@@ -7,6 +7,15 @@
 LL | impl_add!(a b);
    | --------------- in this macro invocation
 
-error: aborting due to previous error
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/issue-53251.rs:11:24
+   |
+LL |                 S::f::<i64>();
+   |                        ^^^ unexpected type argument
+...
+LL | impl_add!(a b);
+   | --------------- in this macro invocation
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr
index 3830ad4..5222e3e 100644
--- a/src/test/ui/issues/issue-54062.stderr
+++ b/src/test/ui/issues/issue-54062.stderr
@@ -4,7 +4,7 @@
 LL |     let _ = test.comps.inner.lock().unwrap();
    |             ^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `unwrap` found for type `std::sys_common::mutex::MutexGuard<'_>` in the current scope
+error[E0599]: no method named `unwrap` found for struct `std::sys_common::mutex::MutexGuard<'_>` in the current scope
   --> $DIR/issue-54062.rs:10:37
    |
 LL |     let _ = test.comps.inner.lock().unwrap();
diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr
index c4000c8..ad596db 100644
--- a/src/test/ui/issues/issue-57362-1.stderr
+++ b/src/test/ui/issues/issue-57362-1.stderr
@@ -1,10 +1,10 @@
-error[E0599]: no method named `f` found for type `fn(&u8)` in the current scope
+error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope
   --> $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
+   = note: `a` is a function, perhaps you wish to call it
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `f`, perhaps you need to implement it:
            candidate #1: `Trait`
diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr
index 2e713cc..3528084 100644
--- a/src/test/ui/issues/issue-57362-2.stderr
+++ b/src/test/ui/issues/issue-57362-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `make_g` found for type `for<'r> fn(&'r ())` in the current scope
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope
   --> $DIR/issue-57362-2.rs:22:25
    |
 LL |     let x = <fn (&())>::make_g();
diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr
index ef0d66d..70a7c38 100644
--- a/src/test/ui/issues/issue-58022.stderr
+++ b/src/test/ui/issues/issue-58022.stderr
@@ -11,9 +11,13 @@
    |     ------------------ required by `Foo::SIZE`
 LL | 
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-   |                         ^^^^^^^^^ cannot infer type
+   |                         ^^^^^^^^^
+   |                         |
+   |                         cannot infer type
+   |                         help: use the fully qualified path to an implementation: `<Type as Foo>::SIZE`
    |
    = note: cannot resolve `_: Foo`
+   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-58344.stderr b/src/test/ui/issues/issue-58344.stderr
index 427d03b..e0c196e 100644
--- a/src/test/ui/issues/issue-58344.stderr
+++ b/src/test/ui/issues/issue-58344.stderr
@@ -3,6 +3,9 @@
    |
 LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
+...
+LL |     add_generic(value, 1u32)
+   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
    |
    = note: the return type of a function must have a statically known size
 
@@ -11,6 +14,9 @@
    |
 LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
+...
+LL |     add_generic(value, 1u32)
+   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/issues/issue-58734.rs b/src/test/ui/issues/issue-58734.rs
index bbdfebe..b253c13 100644
--- a/src/test/ui/issues/issue-58734.rs
+++ b/src/test/ui/issues/issue-58734.rs
@@ -18,5 +18,5 @@
     Trait::exists(());
     // no object safety error
     Trait::nonexistent(());
-    //~^ ERROR no function or associated item named `nonexistent` found for type `dyn Trait`
+    //~^ ERROR no function or associated item named `nonexistent` found
 }
diff --git a/src/test/ui/issues/issue-58734.stderr b/src/test/ui/issues/issue-58734.stderr
index 07f2a04..5e98cfa 100644
--- a/src/test/ui/issues/issue-58734.stderr
+++ b/src/test/ui/issues/issue-58734.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `nonexistent` found for type `dyn Trait` in the current scope
+error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope
   --> $DIR/issue-58734.rs:20:12
    |
 LL |     Trait::nonexistent(());
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index c2de1d0..d886ecc 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -14,6 +14,9 @@
    |
 LL |     -> Struct {
    |        ^^^^^^ doesn't have a size known at compile-time
+LL |
+LL |     Struct { r: r }
+   |     --------------- this returned value is of type `Struct`
    |
    = help: within `Struct`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/issues/issue-59029-1.rs
index e98a4d0..8ab47a4 100644
--- a/src/test/ui/issues/issue-59029-1.rs
+++ b/src/test/ui/issues/issue-59029-1.rs
@@ -4,5 +4,6 @@
 
 trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
 //~^ ERROR associated type `Res` not found for `Self`
+//~| ERROR associated type `Res` not found for `Self`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/issues/issue-59029-1.stderr
index fb1de97..53cdb8b 100644
--- a/src/test/ui/issues/issue-59029-1.stderr
+++ b/src/test/ui/issues/issue-59029-1.stderr
@@ -4,6 +4,12 @@
 LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
    |                                                    ^^^ associated type `Res` not found
 
-error: aborting due to previous error
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:52
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                                    ^^^ associated type `Res` not found
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-62554.rs b/src/test/ui/issues/issue-62554.rs
index 20e84ec..cfd0218 100644
--- a/src/test/ui/issues/issue-62554.rs
+++ b/src/test/ui/issues/issue-62554.rs
@@ -1,5 +1,6 @@
+// error-pattern:this file contains an unclosed delimiter
+// error-pattern:xpected `{`, found `macro_rules`
+
 fn main() {}
 
 fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-//~^ ERROR expected `{`, found `macro_rules`
-//~ ERROR this file contains an unclosed delimiter
diff --git a/src/test/ui/issues/issue-62554.stderr b/src/test/ui/issues/issue-62554.stderr
index 692bfe0..935d384 100644
--- a/src/test/ui/issues/issue-62554.stderr
+++ b/src/test/ui/issues/issue-62554.stderr
@@ -1,18 +1,60 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:5:52
+  --> $DIR/issue-62554.rs:6:89
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  - unclosed delimiter
-   |               |                       |         |                  |
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
    |               |                       |         |                  unclosed delimiter
    |               |                       |         unclosed delimiter
    |               unclosed delimiter      unclosed delimiter
-LL |
-LL |
-   |                                                    ^
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62554.rs:6:89
+   |
+LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
+   |               -                       -         -                  -                  - ^
+   |               |                       |         |                  |                  |
+   |               |                       |         |                  |                  unclosed delimiter
+   |               |                       |         |                  unclosed delimiter
+   |               |                       |         unclosed delimiter
+   |               unclosed delimiter      unclosed delimiter
 
 error: expected `{`, found `macro_rules`
-  --> $DIR/issue-62554.rs:3:23
+  --> $DIR/issue-62554.rs:6:23
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
    |                 --    ^^^^^^^^^^^ expected `{`
@@ -22,10 +64,8 @@
 help: try placing this code inside a block
    |
 LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-LL |
-LL |
 LL |  }
    |
 
-error: aborting due to 2 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr
index f1b2de8..e7a244e 100644
--- a/src/test/ui/issues/issue-64430.stderr
+++ b/src/test/ui/issues/issue-64430.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `bar` found for type `Foo` in the current scope
+error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/issue-64430.rs:7:9
    |
 LL | pub struct Foo;
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
index e0eaafd..018ce04 100644
--- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
@@ -5,7 +5,7 @@
 trait Bar {}
 
 fn do_stuff<T : Bar>(t : T) {
-    t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope
+    t.foo() //~ ERROR no method named `foo` found
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
index 24bf60a..4807a09 100644
--- a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `T` in the current scope
+error[E0599]: no method named `foo` found for type parameter `T` in the current scope
   --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
    |
 LL |     t.foo()
diff --git a/src/test/ui/issues/issue-66308.rs b/src/test/ui/issues/issue-66308.rs
new file mode 100644
index 0000000..8460b35
--- /dev/null
+++ b/src/test/ui/issues/issue-66308.rs
@@ -0,0 +1,8 @@
+// build-pass
+// compile-flags: --crate-type lib -C opt-level=0
+
+// Regression test for LLVM crash affecting Emscripten targets
+
+pub fn foo() {
+    (0..0).rev().next();
+}
diff --git a/src/test/ui/issues/issue-66473.rs b/src/test/ui/issues/issue-66473.rs
new file mode 100644
index 0000000..cc298a2
--- /dev/null
+++ b/src/test/ui/issues/issue-66473.rs
Binary files differ
diff --git a/src/test/ui/issues/issue-66473.stderr b/src/test/ui/issues/issue-66473.stderr
new file mode 100644
index 0000000..dbeef44
--- /dev/null
+++ b/src/test/ui/issues/issue-66473.stderr
Binary files differ
diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs
new file mode 100644
index 0000000..3c49a5a
--- /dev/null
+++ b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs
@@ -0,0 +1,6 @@
+pub struct Foo {
+    pub bar: Vec<i32>ö
+    //~^ ERROR expected `,`, or `}`, found `ö`
+} //~ ERROR expected `:`, found `}`
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr
new file mode 100644
index 0000000..ef365a6
--- /dev/null
+++ b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr
@@ -0,0 +1,17 @@
+error: expected `,`, or `}`, found `ö`
+  --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:2:22
+   |
+LL |     pub bar: Vec<i32>ö
+   |                      ^ help: try adding a comma: `,`
+
+error: expected `:`, found `}`
+  --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:4:1
+   |
+LL |     pub bar: Vec<i32>ö
+   |                       - expected `:`
+LL |
+LL | }
+   | ^ unexpected token
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/issues/issue-6804.rs
index b4af358..3251373 100644
--- a/src/test/ui/issues/issue-6804.rs
+++ b/src/test/ui/issues/issue-6804.rs
@@ -17,7 +17,9 @@
 
     match [x, 1.0] {
         [NAN, _] => {}, //~ ERROR floating-point types cannot be used
-        //~^ WARN this was previously accepted by the compiler but is being phased out
+                        //~| ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        //~| WARN this was previously accepted by the compiler but is being phased out
         _ => {},
     };
 }
diff --git a/src/test/ui/issues/issue-6804.stderr b/src/test/ui/issues/issue-6804.stderr
index ab4467e..f4188dc 100644
--- a/src/test/ui/issues/issue-6804.stderr
+++ b/src/test/ui/issues/issue-6804.stderr
@@ -30,5 +30,14 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to 3 previous errors
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:19:10
+   |
+LL |         [NAN, _] => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs b/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs
new file mode 100644
index 0000000..00f90cc
--- /dev/null
+++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs
@@ -0,0 +1,9 @@
+macro_rules! x {
+    ($($c:tt)*) => {
+        $($c)ö* {} //~ ERROR missing condition for `if` expression
+    };             //~| ERROR mismatched types
+}
+
+fn main() {
+    x!(if);
+}
diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr
new file mode 100644
index 0000000..8d1a03a
--- /dev/null
+++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr
@@ -0,0 +1,18 @@
+error: missing condition for `if` expression
+  --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14
+   |
+LL |         $($c)ö* {}
+   |              ^ expected if condition here
+
+error[E0308]: mismatched types
+  --> $DIR/issue-68091-unicode-ident-after-if.rs:3:17
+   |
+LL |         $($c)ö* {}
+   |                 ^^ expected `bool`, found `()`
+...
+LL |     x!(if);
+   |     ------- in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs
new file mode 100644
index 0000000..1a90b47
--- /dev/null
+++ b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs
@@ -0,0 +1,9 @@
+macro_rules! x {
+    ($($c:tt)*) => {
+        $($c)ö* //~ ERROR macro expansion ends with an incomplete expression: expected expression
+    };
+}
+
+fn main() {
+    x!(!);
+}
diff --git a/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr
new file mode 100644
index 0000000..0b9c364
--- /dev/null
+++ b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr
@@ -0,0 +1,8 @@
+error: macro expansion ends with an incomplete expression: expected expression
+  --> $DIR/issue-68092-unicode-ident-after-incomplete-expr.rs:3:14
+   |
+LL |         $($c)ö*
+   |              ^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-68103.rs b/src/test/ui/issues/issue-68103.rs
new file mode 100644
index 0000000..e775678
--- /dev/null
+++ b/src/test/ui/issues/issue-68103.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+pub extern crate self as name;
+pub use name::name as bug;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-7607-1.rs b/src/test/ui/issues/issue-7607-1.rs
index 5221f2c..1571cd2 100644
--- a/src/test/ui/issues/issue-7607-1.rs
+++ b/src/test/ui/issues/issue-7607-1.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 struct Foo {
     x: isize
 }
diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr
index 9320943..94f489e 100644
--- a/src/test/ui/issues/issue-7607-1.stderr
+++ b/src/test/ui/issues/issue-7607-1.stderr
@@ -1,8 +1,13 @@
 error[E0412]: cannot find type `Fo` in this scope
-  --> $DIR/issue-7607-1.rs:5:6
+  --> $DIR/issue-7607-1.rs:9:6
    |
 LL | impl Fo {
    |      ^^ help: a trait with a similar name exists: `Fn`
+   | 
+  ::: $SRC_DIR/libcore/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-7784.rs b/src/test/ui/issues/issue-7784.rs
index 5b70bd6..b7323f0 100644
--- a/src/test/ui/issues/issue-7784.rs
+++ b/src/test/ui/issues/issue-7784.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 use std::ops::Add;
 
diff --git a/src/test/ui/issues/issue-7950.rs b/src/test/ui/issues/issue-7950.rs
index 7add8af..d3dcb33 100644
--- a/src/test/ui/issues/issue-7950.rs
+++ b/src/test/ui/issues/issue-7950.rs
@@ -4,5 +4,5 @@
 
 fn main() {
     Foo::bar();
-    //~^ ERROR no function or associated item named `bar` found for type `Foo`
+    //~^ ERROR no function or associated item named `bar` found for struct `Foo`
 }
diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr
index bbeab40..73e13c6 100644
--- a/src/test/ui/issues/issue-7950.stderr
+++ b/src/test/ui/issues/issue-7950.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `bar` found for type `Foo` in the current scope
+error[E0599]: no function or associated item named `bar` found for struct `Foo` in the current scope
   --> $DIR/issue-7950.rs:6:10
    |
 LL | struct Foo;
diff --git a/src/test/ui/iterators/skip-count-overflow.rs b/src/test/ui/iterators/skip-count-overflow.rs
new file mode 100644
index 0000000..d8efc94
--- /dev/null
+++ b/src/test/ui/iterators/skip-count-overflow.rs
@@ -0,0 +1,8 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// compile-flags: -C overflow-checks -C opt-level=3
+
+fn main() {
+    let i = (0..usize::max_value()).chain(0..10).skip(usize::max_value());
+    assert_eq!(i.count(), 10);
+}
diff --git a/src/test/ui/keyword/keyword-super-as-identifier.rs b/src/test/ui/keyword/keyword-super-as-identifier.rs
index d728b4f..02c1b27 100644
--- a/src/test/ui/keyword/keyword-super-as-identifier.rs
+++ b/src/test/ui/keyword/keyword-super-as-identifier.rs
@@ -1,3 +1,3 @@
 fn main() {
-    let super = 22; //~ ERROR failed to resolve: there are too many initial `super`s
+    let super = 22; //~ ERROR failed to resolve: there are too many leading `super` keywords
 }
diff --git a/src/test/ui/keyword/keyword-super-as-identifier.stderr b/src/test/ui/keyword/keyword-super-as-identifier.stderr
index bbeaed9..1f64f3b 100644
--- a/src/test/ui/keyword/keyword-super-as-identifier.stderr
+++ b/src/test/ui/keyword/keyword-super-as-identifier.stderr
@@ -1,8 +1,8 @@
-error[E0433]: failed to resolve: there are too many initial `super`s.
+error[E0433]: failed to resolve: there are too many leading `super` keywords
   --> $DIR/keyword-super-as-identifier.rs:2:9
    |
 LL |     let super = 22;
-   |         ^^^^^ there are too many initial `super`s.
+   |         ^^^^^ there are too many leading `super` keywords
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/keyword/keyword-super.rs b/src/test/ui/keyword/keyword-super.rs
index a43e1e3..c121a6c 100644
--- a/src/test/ui/keyword/keyword-super.rs
+++ b/src/test/ui/keyword/keyword-super.rs
@@ -1,3 +1,3 @@
 fn main() {
-    let super: isize; //~ ERROR failed to resolve: there are too many initial `super`s
+    let super: isize; //~ ERROR failed to resolve: there are too many leading `super` keywords
 }
diff --git a/src/test/ui/keyword/keyword-super.stderr b/src/test/ui/keyword/keyword-super.stderr
index 63394c7..0e0d67c 100644
--- a/src/test/ui/keyword/keyword-super.stderr
+++ b/src/test/ui/keyword/keyword-super.stderr
@@ -1,8 +1,8 @@
-error[E0433]: failed to resolve: there are too many initial `super`s.
+error[E0433]: failed to resolve: there are too many leading `super` keywords
   --> $DIR/keyword-super.rs:2:9
    |
 LL |     let super: isize;
-   |         ^^^^^ there are too many initial `super`s.
+   |         ^^^^^ there are too many leading `super` keywords
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr
index 40b67f8..39640e3 100644
--- a/src/test/ui/kindck/kindck-nonsendable-1.stderr
+++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr
@@ -5,7 +5,9 @@
    |    ---              ---- required by this bound in `bar`
 ...
 LL |     bar(move|| foo(x));
-   |     ^^^ `std::rc::Rc<usize>` cannot be sent between threads safely
+   |     ^^^ ------------- within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`
+   |     |
+   |     `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>]`
diff --git a/src/test/ui/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/ui/lexer-crlf-line-endings-string-literal-doc-comment.rs
index ada253a..802be7f 100644
--- a/src/test/ui/lexer-crlf-line-endings-string-literal-doc-comment.rs
+++ b/src/test/ui/lexer-crlf-line-endings-string-literal-doc-comment.rs
@@ -1,11 +1,8 @@
 // run-pass

-// ignore-tidy-cr ignore-license

+// ignore-tidy-cr

 // ignore-tidy-cr (repeated again because of tidy bug)

 // license is ignored because tidy can't handle the CRLF here properly.

 

-// http://rust-lang.org/COPYRIGHT.

-//

-

 // N.B., this file needs CRLF line endings. The .gitattributes file in

 // this directory should enforce it.

 

diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index a7843a9..6bb0877 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -9,7 +9,7 @@
 LL | use T;
    |
 
-error[E0599]: no function or associated item named `f` found for type `Foo` in the current scope
+error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope
   --> $DIR/lexical-scopes.rs:10:10
    |
 LL |     Foo::f();
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
index 3f7c393..1d5eeac 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
@@ -10,17 +10,25 @@
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33
    |
 LL | fn g(_x: &isize, _y: &isize) -> &isize {
-   |                                 ^ expected lifetime parameter
+   |                                 ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn g<'lifetime>(_x: &isize, _y: &isize) -> &'lifetime isize {
+   |     ^^^^^^^^^^^                            ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19
    |
 LL | fn h(_x: &Foo) -> &isize {
-   |                   ^ expected lifetime parameter
+   |                   ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL | fn h<'lifetime>(_x: &Foo) -> &'lifetime isize {
+   |     ^^^^^^^^^^^              ^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
index 228582d..e43fb6d 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
@@ -3,6 +3,9 @@
    |
 LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
+LL |
+LL |     Ok(())
+   |     ------ this returned value is of type `std::result::Result<(), _>`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
index a4e0d71..2990ab8 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
@@ -2,9 +2,13 @@
   --> $DIR/ex1b-return-no-names-if-else.rs:1:29
    |
 LL | fn foo(x: &i32, y: &i32) -> &i32 {
-   |                             ^ expected lifetime parameter
+   |                             ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'lifetime>(x: &i32, y: &i32) -> &'lifetime i32 {
+   |       ^^^^^^^^^^^                      ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/command-line-lint-group-allow.rs b/src/test/ui/lint/command-line-lint-group-allow.rs
index f26e157..21c0df0 100644
--- a/src/test/ui/lint/command-line-lint-group-allow.rs
+++ b/src/test/ui/lint/command-line-lint-group-allow.rs
@@ -1,5 +1,5 @@
 // compile-flags: -A bad-style
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 fn main() {
     let _InappropriateCamelCasing = true;
diff --git a/src/test/ui/lint/dead-code/tuple-struct-field.rs b/src/test/ui/lint/dead-code/tuple-struct-field.rs
index 92a6795..c8fd32c 100644
--- a/src/test/ui/lint/dead-code/tuple-struct-field.rs
+++ b/src/test/ui/lint/dead-code/tuple-struct-field.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![deny(dead_code)]
 
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
index 9fce66a..d6e5033 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // run-rustfix
 
 #![warn(ellipsis_inclusive_range_patterns)]
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
index f886e77..773eea1 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // run-rustfix
 
 #![warn(ellipsis_inclusive_range_patterns)]
diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs
new file mode 100644
index 0000000..c2b8195
--- /dev/null
+++ b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs
@@ -0,0 +1,29 @@
+#![deny(non_snake_case)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+enum Foo {
+    Bad {
+        lowerCamelCaseName: bool,
+        //~^ ERROR structure field `lowerCamelCaseName` should have a snake case name
+    },
+    Good {
+        snake_case_name: bool,
+    },
+}
+
+fn main() {
+    let b = Foo::Bad { lowerCamelCaseName: true };
+
+    match b {
+        Foo::Bad { lowerCamelCaseName } => {}
+        Foo::Good { snake_case_name: lowerCamelCaseBinding } => { }
+        //~^ ERROR variable `lowerCamelCaseBinding` should have a snake case name
+    }
+
+    if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { }
+    //~^ ERROR variable `anotherLowerCamelCaseBinding` should have a snake case name
+
+    if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { }
+    //~^ ERROR variable `yetAnotherLowerCamelCaseBinding` should have a snake case name
+}
diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr
new file mode 100644
index 0000000..68956f2
--- /dev/null
+++ b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr
@@ -0,0 +1,32 @@
+error: structure field `lowerCamelCaseName` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9
+   |
+LL |         lowerCamelCaseName: bool,
+   |         ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name`
+   |
+note: lint level defined here
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: variable `lowerCamelCaseBinding` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38
+   |
+LL |         Foo::Good { snake_case_name: lowerCamelCaseBinding } => { }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding`
+
+error: variable `anotherLowerCamelCaseBinding` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41
+   |
+LL |     if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding`
+
+error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43
+   |
+LL |     if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { }
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lint/lint-forbid-attr.rs b/src/test/ui/lint/lint-forbid-attr.rs
index 082b543..13b28e8 100644
--- a/src/test/ui/lint/lint-forbid-attr.rs
+++ b/src/test/ui/lint/lint-forbid-attr.rs
@@ -2,5 +2,7 @@
 
 #[allow(deprecated)]
 //~^ ERROR allow(deprecated) overruled by outer forbid(deprecated)
+//~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
+//~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
 }
diff --git a/src/test/ui/lint/lint-forbid-attr.stderr b/src/test/ui/lint/lint-forbid-attr.stderr
index 6e1e2b3..bf138c3 100644
--- a/src/test/ui/lint/lint-forbid-attr.stderr
+++ b/src/test/ui/lint/lint-forbid-attr.stderr
@@ -7,6 +7,24 @@
 LL | #[allow(deprecated)]
    |         ^^^^^^^^^^ overruled by previous forbid
 
-error: aborting due to previous error
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-attr.rs:3:9
+   |
+LL | #![forbid(deprecated)]
+   |           ---------- `forbid` level set here
+LL | 
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-attr.rs:3:9
+   |
+LL | #![forbid(deprecated)]
+   |           ---------- `forbid` level set here
+LL | 
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/lint-forbid-cmdline.rs b/src/test/ui/lint/lint-forbid-cmdline.rs
index 150685c..821470c 100644
--- a/src/test/ui/lint/lint-forbid-cmdline.rs
+++ b/src/test/ui/lint/lint-forbid-cmdline.rs
@@ -1,5 +1,7 @@
 // compile-flags: -F deprecated
 
 #[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
+                     //~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
+                     //~| ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
 }
diff --git a/src/test/ui/lint/lint-forbid-cmdline.stderr b/src/test/ui/lint/lint-forbid-cmdline.stderr
index bece477..89a4445 100644
--- a/src/test/ui/lint/lint-forbid-cmdline.stderr
+++ b/src/test/ui/lint/lint-forbid-cmdline.stderr
@@ -6,6 +6,22 @@
    |
    = note: `forbid` lint level was set on command line
 
-error: aborting due to previous error
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-cmdline.rs:3:9
+   |
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error[E0453]: allow(deprecated) overruled by outer forbid(deprecated)
+  --> $DIR/lint-forbid-cmdline.rs:3:9
+   |
+LL | #[allow(deprecated)]
+   |         ^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: `forbid` lint level was set on command line
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs b/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
index 95da4ef..d085db4 100644
--- a/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
+++ b/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // Issue #7526: lowercase static constants in patterns look like bindings
 
 // This is similar to lint-lowercase-static-const-pattern.rs, except it
diff --git a/src/test/ui/lint/lint-malformed.rs b/src/test/ui/lint/lint-malformed.rs
index 0d32767..cf55707 100644
--- a/src/test/ui/lint/lint-malformed.rs
+++ b/src/test/ui/lint/lint-malformed.rs
@@ -1,4 +1,8 @@
 #![deny = "foo"] //~ ERROR malformed `deny` attribute input
 #![allow(bar = "baz")] //~ ERROR malformed lint attribute
-
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
+                       //~| ERROR malformed lint attribute
 fn main() { }
diff --git a/src/test/ui/lint/lint-malformed.stderr b/src/test/ui/lint/lint-malformed.stderr
index f487629..6dc8d49 100644
--- a/src/test/ui/lint/lint-malformed.stderr
+++ b/src/test/ui/lint/lint-malformed.stderr
@@ -4,12 +4,42 @@
 LL | #![allow(bar = "baz")]
    |          ^^^^^^^^^^^ bad attribute argument
 
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
 error: malformed `deny` attribute input
   --> $DIR/lint-malformed.rs:1:1
    |
 LL | #![deny = "foo"]
    | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]`
 
-error: aborting due to 2 previous errors
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/lint-malformed.rs:2:10
+   |
+LL | #![allow(bar = "baz")]
+   |          ^^^^^^^^^^^ bad attribute argument
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/lint/lint-non-camel-case-variant.rs b/src/test/ui/lint/lint-non-camel-case-variant.rs
index 434e24c..2b1a52f 100644
--- a/src/test/ui/lint/lint-non-camel-case-variant.rs
+++ b/src/test/ui/lint/lint-non-camel-case-variant.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![deny(non_camel_case_types)]
 
diff --git a/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs b/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
index d025ee9..b832e4b 100644
--- a/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
+++ b/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(dead_code)]
 // This is ok because we often use the trailing underscore to mean 'prime'
diff --git a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
index 5bec82c..710eebe 100644
--- a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
+++ b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode.rs b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
index 40f0a67..9f16cb2 100644
--- a/src/test/ui/lint/lint-nonstandard-style-unicode.rs
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/lint/lint-output-format-2.rs b/src/test/ui/lint/lint-output-format-2.rs
index 32a4117..521472d 100644
--- a/src/test/ui/lint/lint-output-format-2.rs
+++ b/src/test/ui/lint/lint-output-format-2.rs
@@ -1,7 +1,7 @@
 // aux-build:lint_output_format.rs
 
 #![feature(unstable_test_feature)]
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 extern crate lint_output_format;
 use lint_output_format::{foo, bar};
diff --git a/src/test/ui/lint/lint-removed-cmdline.stderr b/src/test/ui/lint/lint-removed-cmdline.stderr
index 69b0d26..b4ab5f5 100644
--- a/src/test/ui/lint/lint-removed-cmdline.stderr
+++ b/src/test/ui/lint/lint-removed-cmdline.stderr
@@ -2,6 +2,18 @@
    |
    = note: requested on the command line with `-D raw_pointer_derive`
 
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
+warning: lint `raw_pointer_derive` has been removed: `using derive with raw pointers is ok`
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+
 error: unused variable: `unused`
   --> $DIR/lint-removed-cmdline.rs:12:17
    |
diff --git a/src/test/ui/lint/lint-renamed-cmdline.stderr b/src/test/ui/lint/lint-renamed-cmdline.stderr
index c978981..6401d9b 100644
--- a/src/test/ui/lint/lint-renamed-cmdline.stderr
+++ b/src/test/ui/lint/lint-renamed-cmdline.stderr
@@ -2,6 +2,18 @@
    |
    = note: requested on the command line with `-D bare_trait_object`
 
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
+warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+   |
+   = note: requested on the command line with `-D bare_trait_object`
+
 error: unused variable: `unused`
   --> $DIR/lint-renamed-cmdline.rs:8:17
    |
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
index 0585fec..4b407a2 100644
--- a/src/test/ui/lint/lint-stability-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // aux-build:lint_stability.rs
 // aux-build:inherited_stability.rs
 // aux-build:stability_cfg1.rs
@@ -97,10 +97,13 @@
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
         //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+        //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
         type A = dyn TraitWithAssociatedTypes<
             TypeUnstable = u8,
             TypeDeprecated = u16,
             //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
+            //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
+            //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
         >;
 
         let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr
index 6238013..650373c 100644
--- a/src/test/ui/lint/lint-stability-deprecated.stderr
+++ b/src/test/ui/lint/lint-stability-deprecated.stderr
@@ -77,241 +77,241 @@
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
-  --> $DIR/lint-stability-deprecated.rs:106:17
+  --> $DIR/lint-stability-deprecated.rs:109:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct': text
-  --> $DIR/lint-stability-deprecated.rs:109:17
+  --> $DIR/lint-stability-deprecated.rs:112:17
    |
 LL |         let _ = DeprecatedUnstableStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:116:17
+  --> $DIR/lint-stability-deprecated.rs:119:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:117:17
+  --> $DIR/lint-stability-deprecated.rs:120:17
    |
 LL |         let _ = DeprecatedUnstableUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Enum::DeprecatedVariant': text
-  --> $DIR/lint-stability-deprecated.rs:121:17
+  --> $DIR/lint-stability-deprecated.rs:124:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant': text
-  --> $DIR/lint-stability-deprecated.rs:122:17
+  --> $DIR/lint-stability-deprecated.rs:125:17
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:126:17
+  --> $DIR/lint-stability-deprecated.rs:129:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:127:17
+  --> $DIR/lint-stability-deprecated.rs:130:17
    |
 LL |         let _ = DeprecatedUnstableTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:136:25
+  --> $DIR/lint-stability-deprecated.rs:139:25
    |
 LL |         macro_test_arg!(deprecated_text());
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:137:25
+  --> $DIR/lint-stability-deprecated.rs:140:25
    |
 LL |         macro_test_arg!(deprecated_unstable_text());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:138:41
+  --> $DIR/lint-stability-deprecated.rs:141:41
    |
 LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:143:9
+  --> $DIR/lint-stability-deprecated.rs:146:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:145:9
+  --> $DIR/lint-stability-deprecated.rs:148:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:147:9
+  --> $DIR/lint-stability-deprecated.rs:150:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:149:9
+  --> $DIR/lint-stability-deprecated.rs:152:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:151:9
+  --> $DIR/lint-stability-deprecated.rs:154:9
    |
 LL |         Trait::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:153:9
+  --> $DIR/lint-stability-deprecated.rs:156:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:155:9
+  --> $DIR/lint-stability-deprecated.rs:158:9
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:157:9
+  --> $DIR/lint-stability-deprecated.rs:160:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:185:10
+  --> $DIR/lint-stability-deprecated.rs:188:10
    |
 LL |     impl DeprecatedTrait for S {}
    |          ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:187:25
+  --> $DIR/lint-stability-deprecated.rs:190:25
    |
 LL |     trait LocalTrait2 : DeprecatedTrait { }
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:206:9
+  --> $DIR/lint-stability-deprecated.rs:209:9
    |
 LL |         unstable_mod::deprecated();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:328:9
+  --> $DIR/lint-stability-deprecated.rs:331:9
    |
 LL |         deprecated();
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:333:9
+  --> $DIR/lint-stability-deprecated.rs:336:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:335:9
+  --> $DIR/lint-stability-deprecated.rs:338:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:337:9
+  --> $DIR/lint-stability-deprecated.rs:340:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:342:9
+  --> $DIR/lint-stability-deprecated.rs:345:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:344:9
+  --> $DIR/lint-stability-deprecated.rs:347:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedStruct': text
-  --> $DIR/lint-stability-deprecated.rs:382:17
+  --> $DIR/lint-stability-deprecated.rs:385:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:389:17
+  --> $DIR/lint-stability-deprecated.rs:392:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
-  --> $DIR/lint-stability-deprecated.rs:393:17
+  --> $DIR/lint-stability-deprecated.rs:396:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:397:17
+  --> $DIR/lint-stability-deprecated.rs:400:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:404:9
+  --> $DIR/lint-stability-deprecated.rs:407:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:406:9
+  --> $DIR/lint-stability-deprecated.rs:409:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:408:9
+  --> $DIR/lint-stability-deprecated.rs:411:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:410:9
+  --> $DIR/lint-stability-deprecated.rs:413:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
-  --> $DIR/lint-stability-deprecated.rs:437:9
+  --> $DIR/lint-stability-deprecated.rs:440:9
    |
 LL |         fn_in_body();
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:457:10
+  --> $DIR/lint-stability-deprecated.rs:460:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:459:24
+  --> $DIR/lint-stability-deprecated.rs:462:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
-  --> $DIR/lint-stability-deprecated.rs:445:13
+  --> $DIR/lint-stability-deprecated.rs:448:13
    |
 LL |             fn_in_body();
    |             ^^^^^^^^^^
@@ -323,7 +323,7 @@
    |                                                ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
-  --> $DIR/lint-stability-deprecated.rs:102:13
+  --> $DIR/lint-stability-deprecated.rs:103:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
@@ -449,188 +449,206 @@
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:107:13
+  --> $DIR/lint-stability-deprecated.rs:110:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:111:13
+  --> $DIR/lint-stability-deprecated.rs:114:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:142:13
+  --> $DIR/lint-stability-deprecated.rs:145:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:144:9
+  --> $DIR/lint-stability-deprecated.rs:147:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:146:13
+  --> $DIR/lint-stability-deprecated.rs:149:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:148:9
+  --> $DIR/lint-stability-deprecated.rs:151:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:150:13
+  --> $DIR/lint-stability-deprecated.rs:153:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:152:9
+  --> $DIR/lint-stability-deprecated.rs:155:9
    |
 LL |         <Foo>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:154:13
+  --> $DIR/lint-stability-deprecated.rs:157:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:156:9
+  --> $DIR/lint-stability-deprecated.rs:159:9
    |
 LL | ...   <Foo>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:173:13
+  --> $DIR/lint-stability-deprecated.rs:176:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:174:13
+  --> $DIR/lint-stability-deprecated.rs:177:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:175:13
+  --> $DIR/lint-stability-deprecated.rs:178:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:176:13
+  --> $DIR/lint-stability-deprecated.rs:179:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:329:13
+  --> $DIR/lint-stability-deprecated.rs:332:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:330:9
+  --> $DIR/lint-stability-deprecated.rs:333:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:331:9
+  --> $DIR/lint-stability-deprecated.rs:334:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:332:13
+  --> $DIR/lint-stability-deprecated.rs:335:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:334:9
+  --> $DIR/lint-stability-deprecated.rs:337:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:338:13
+  --> $DIR/lint-stability-deprecated.rs:341:13
    |
 LL |         foo.method_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:339:9
+  --> $DIR/lint-stability-deprecated.rs:342:9
    |
 LL |         Foo::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:340:9
+  --> $DIR/lint-stability-deprecated.rs:343:9
    |
 LL |         <Foo>::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:341:13
+  --> $DIR/lint-stability-deprecated.rs:344:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:343:9
+  --> $DIR/lint-stability-deprecated.rs:346:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:384:13
+  --> $DIR/lint-stability-deprecated.rs:387:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:403:13
+  --> $DIR/lint-stability-deprecated.rs:406:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:405:9
+  --> $DIR/lint-stability-deprecated.rs:408:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:407:13
+  --> $DIR/lint-stability-deprecated.rs:410:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:409:9
+  --> $DIR/lint-stability-deprecated.rs:412:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:426:13
+  --> $DIR/lint-stability-deprecated.rs:429:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:427:13
+  --> $DIR/lint-stability-deprecated.rs:430:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:98:48
+   |
+LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+   |                                                ^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:103:13
+   |
+LL |             TypeDeprecated = u16,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+  --> $DIR/lint-stability-deprecated.rs:103:13
+   |
+LL |             TypeDeprecated = u16,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/lint-unexported-no-mangle.stderr b/src/test/ui/lint/lint-unexported-no-mangle.stderr
index c2cbf5f..3a78ed2 100644
--- a/src/test/ui/lint/lint-unexported-no-mangle.stderr
+++ b/src/test/ui/lint/lint-unexported-no-mangle.stderr
@@ -6,6 +6,30 @@
    |
    = note: requested on the command line with `-F private_no_mangle_statics`
 
+warning: lint `private_no_mangle_fns` has been removed: `no longer a warning, `#[no_mangle]` functions always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_fns`
+
+warning: lint `private_no_mangle_statics` has been removed: `no longer a warning, `#[no_mangle]` statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
+warning: lint `private_no_mangle_fns` has been removed: `no longer a warning, `#[no_mangle]` functions always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_fns`
+
+warning: lint `private_no_mangle_statics` has been removed: `no longer a warning, `#[no_mangle]` statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
+warning: lint `private_no_mangle_fns` has been removed: `no longer a warning, `#[no_mangle]` functions always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_fns`
+
+warning: lint `private_no_mangle_statics` has been removed: `no longer a warning, `#[no_mangle]` statics always exported`
+   |
+   = note: requested on the command line with `-F private_no_mangle_statics`
+
 error: const items should never be `#[no_mangle]`
   --> $DIR/lint-unexported-no-mangle.rs:9:1
    |
diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
index 58fdae3..27e7ee7 100644
--- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
+++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr
@@ -7,6 +7,24 @@
    = help: did you mean: `dead_code`
    = note: requested on the command line with `-D dead_cod`
 
-error: aborting due to 2 previous errors
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `dead_cod`
+   |
+   = help: did you mean: `dead_code`
+   = note: requested on the command line with `-D dead_cod`
+
+error[E0602]: unknown lint: `bogus`
+   |
+   = note: requested on the command line with `-D bogus`
+
+error[E0602]: unknown lint: `dead_cod`
+   |
+   = help: did you mean: `dead_code`
+   = note: requested on the command line with `-D dead_cod`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs
index 12ffb6d..4e8339a 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.rs
+++ b/src/test/ui/lint/lint-unnecessary-parens.rs
@@ -17,6 +17,13 @@
     panic!()
 }
 
+fn unused_parens_around_block_return() -> u32 {
+    let foo = {
+        (5) //~ ERROR unnecessary parentheses around block return value
+    };
+    (5) //~ ERROR unnecessary parentheses around block return value
+}
+
 trait Trait {
     fn test(&self);
 }
diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr
index 541ae7a..ea58220 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.stderr
+++ b/src/test/ui/lint/lint-unnecessary-parens.stderr
@@ -22,26 +22,38 @@
 LL | fn unused_parens_around_return_type() -> (u32) {
    |                                          ^^^^^ help: remove these parentheses
 
+error: unnecessary parentheses around block return value
+  --> $DIR/lint-unnecessary-parens.rs:22:9
+   |
+LL |         (5)
+   |         ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around block return value
+  --> $DIR/lint-unnecessary-parens.rs:24:5
+   |
+LL |     (5)
+   |     ^^^ help: remove these parentheses
+
 error: unnecessary parentheses around function argument
-  --> $DIR/lint-unnecessary-parens.rs:36:9
+  --> $DIR/lint-unnecessary-parens.rs:43:9
    |
 LL |     bar((true));
    |         ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `if` condition
-  --> $DIR/lint-unnecessary-parens.rs:38:8
+  --> $DIR/lint-unnecessary-parens.rs:45:8
    |
 LL |     if (true) {}
    |        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `while` condition
-  --> $DIR/lint-unnecessary-parens.rs:39:11
+  --> $DIR/lint-unnecessary-parens.rs:46:11
    |
 LL |     while (true) {}
    |           ^^^^^^ help: remove these parentheses
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/lint-unnecessary-parens.rs:39:5
+  --> $DIR/lint-unnecessary-parens.rs:46:5
    |
 LL |     while (true) {}
    |     ^^^^^^^^^^^^ help: use `loop`
@@ -49,46 +61,46 @@
    = note: `#[warn(while_true)]` on by default
 
 error: unnecessary parentheses around `match` head expression
-  --> $DIR/lint-unnecessary-parens.rs:41:11
+  --> $DIR/lint-unnecessary-parens.rs:48:11
    |
 LL |     match (true) {
    |           ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:44:16
+  --> $DIR/lint-unnecessary-parens.rs:51:16
    |
 LL |     if let 1 = (1) {}
    |                ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:45:19
+  --> $DIR/lint-unnecessary-parens.rs:52:19
    |
 LL |     while let 1 = (2) {}
    |                   ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around method argument
-  --> $DIR/lint-unnecessary-parens.rs:59:24
+  --> $DIR/lint-unnecessary-parens.rs:66:24
    |
 LL |     X { y: false }.foo((true));
    |                        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:61:18
+  --> $DIR/lint-unnecessary-parens.rs:68:18
    |
 LL |     let mut _a = (0);
    |                  ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:62:10
+  --> $DIR/lint-unnecessary-parens.rs:69:10
    |
 LL |     _a = (0);
    |          ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:63:11
+  --> $DIR/lint-unnecessary-parens.rs:70:11
    |
 LL |     _a += (1);
    |           ^^^ help: remove these parentheses
 
-error: aborting due to 13 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/test/ui/lint/lint-uppercase-variables.rs b/src/test/ui/lint/lint-uppercase-variables.rs
index 86a3950..a98b4f2 100644
--- a/src/test/ui/lint/lint-uppercase-variables.rs
+++ b/src/test/ui/lint/lint-uppercase-variables.rs
@@ -25,6 +25,16 @@
 //~^^^ WARN unused variable: `Foo`
     }
 
+    let Foo = foo::Foo::Foo;
+    //~^ ERROR variable `Foo` should have a snake case name
+    //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
+    //~^^^ WARN unused variable: `Foo`
+
+    fn in_param(Foo: foo::Foo) {}
+    //~^ ERROR variable `Foo` should have a snake case name
+    //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
+    //~^^^ WARN unused variable: `Foo`
+
     test(1);
 
     let _ = Something { X: 0 };
diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr
index f614d5d..a38f3e7 100644
--- a/src/test/ui/lint/lint-uppercase-variables.stderr
+++ b/src/test/ui/lint/lint-uppercase-variables.stderr
@@ -3,6 +3,20 @@
    |
 LL |         Foo => {}
    |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
+
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
+  --> $DIR/lint-uppercase-variables.rs:28:9
+   |
+LL |     let Foo = foo::Foo::Foo;
+   |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
+
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
+  --> $DIR/lint-uppercase-variables.rs:33:17
+   |
+LL |     fn in_param(Foo: foo::Foo) {}
+   |                 ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
 
 warning: unused variable: `Foo`
   --> $DIR/lint-uppercase-variables.rs:22:9
@@ -17,6 +31,18 @@
    |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
+warning: unused variable: `Foo`
+  --> $DIR/lint-uppercase-variables.rs:28:9
+   |
+LL |     let Foo = foo::Foo::Foo;
+   |         ^^^ help: consider prefixing with an underscore: `_Foo`
+
+warning: unused variable: `Foo`
+  --> $DIR/lint-uppercase-variables.rs:33:17
+   |
+LL |     fn in_param(Foo: foo::Foo) {}
+   |                 ^^^ help: consider prefixing with an underscore: `_Foo`
+
 error: structure field `X` should have a snake case name
   --> $DIR/lint-uppercase-variables.rs:10:5
    |
@@ -47,6 +73,18 @@
 LL |         Foo => {}
    |         ^^^ help: convert the identifier to snake case (notice the capitalization): `foo`
 
-error: aborting due to 4 previous errors
+error: variable `Foo` should have a snake case name
+  --> $DIR/lint-uppercase-variables.rs:28:9
+   |
+LL |     let Foo = foo::Foo::Foo;
+   |         ^^^ help: convert the identifier to snake case (notice the capitalization): `foo`
+
+error: variable `Foo` should have a snake case name
+  --> $DIR/lint-uppercase-variables.rs:33:17
+   |
+LL |     fn in_param(Foo: foo::Foo) {}
+   |                 ^^^ help: convert the identifier to snake case (notice the capitalization): `foo`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0170`.
diff --git a/src/test/ui/lint/lints-in-foreign-macros.rs b/src/test/ui/lint/lints-in-foreign-macros.rs
index e381c81..c96b8f1 100644
--- a/src/test/ui/lint/lints-in-foreign-macros.rs
+++ b/src/test/ui/lint/lints-in-foreign-macros.rs
@@ -1,5 +1,5 @@
 // aux-build:lints-in-foreign-macros.rs
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
 #![warn(missing_docs)]
diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs
index 950533c..2a38565 100644
--- a/src/test/ui/lint/outer-forbid.rs
+++ b/src/test/ui/lint/outer-forbid.rs
@@ -7,12 +7,18 @@
 #![forbid(unused, non_snake_case)]
 
 #[allow(unused_variables)] //~ ERROR overruled
+                           //~| ERROR overruled
+                           //~| ERROR overruled
 fn foo() {}
 
 #[allow(unused)] //~ ERROR overruled
+                 //~| ERROR overruled
+                 //~| ERROR overruled
 fn bar() {}
 
 #[allow(nonstandard_style)] //~ ERROR overruled
+                            //~| ERROR overruled
+                            //~| ERROR overruled
 fn main() {
     println!("hello forbidden world")
 }
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
index 310a5d88..b2e638e 100644
--- a/src/test/ui/lint/outer-forbid.stderr
+++ b/src/test/ui/lint/outer-forbid.stderr
@@ -8,7 +8,7 @@
    |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
 
 error[E0453]: allow(unused) overruled by outer forbid(unused)
-  --> $DIR/outer-forbid.rs:12:9
+  --> $DIR/outer-forbid.rs:14:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |           ------ `forbid` level set here
@@ -17,7 +17,7 @@
    |         ^^^^^^ overruled by previous forbid
 
 error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
-  --> $DIR/outer-forbid.rs:15:9
+  --> $DIR/outer-forbid.rs:19:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
@@ -25,6 +25,60 @@
 LL | #[allow(nonstandard_style)]
    |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
 
-error: aborting due to 3 previous errors
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:9:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+LL | 
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:14:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:19:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:9:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+LL | 
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:14:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(nonstandard_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:19:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs
index 21c2ddd..03cf067 100644
--- a/src/test/ui/lint/reasons-erroneous.rs
+++ b/src/test/ui/lint/reasons-erroneous.rs
@@ -2,24 +2,70 @@
 
 #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason must be a string literal
+//~| NOTE reason must be a string literal
 //~| NOTE reason must be a string literal
 #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason must be a string literal
+//~| NOTE reason must be a string literal
 //~| NOTE reason must be a string literal
 #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
+//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason in lint attribute must come last
+//~| NOTE reason in lint attribute must come last
 //~| NOTE reason in lint attribute must come last
 #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
 //~^ ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| ERROR malformed lint attribute
+//~| NOTE reason in lint attribute must come last
+//~| NOTE reason in lint attribute must come last
 //~| NOTE reason in lint attribute must come last
 #![warn(missing_copy_implementations, reason)]
 //~^ WARN unknown lint
diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr
index 3f925f1..a84167f 100644
--- a/src/test/ui/lint/reasons-erroneous.stderr
+++ b/src/test/ui/lint/reasons-erroneous.stderr
@@ -5,49 +5,187 @@
    |                                                          ^ reason must be a string literal
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:6:40
+  --> $DIR/reasons-erroneous.rs:10:40
    |
 LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:9:29
+  --> $DIR/reasons-erroneous.rs:17:29
    |
 LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:12:23
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
    |
 LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:15:36
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
    |
 LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:18:44
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:56:44
    |
 LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
    |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:21:25
+  --> $DIR/reasons-erroneous.rs:63:25
    |
 LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
 warning: unknown lint: `reason`
-  --> $DIR/reasons-erroneous.rs:24:39
+  --> $DIR/reasons-erroneous.rs:70:39
    |
 LL | #![warn(missing_copy_implementations, reason)]
    |                                       ^^^^^^
    |
    = note: `#[warn(unknown_lints)]` on by default
 
-error: aborting due to 7 previous errors
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:3:58
+   |
+LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
+   |                                                          ^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:10:40
+   |
+LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:56:44
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:63:25
+   |
+LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:3:58
+   |
+LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
+   |                                                          ^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:10:40
+   |
+LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:17:29
+   |
+LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:30:23
+   |
+LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:43:36
+   |
+LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:56:44
+   |
+LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error[E0452]: malformed lint attribute input
+  --> $DIR/reasons-erroneous.rs:63:25
+   |
+LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
+
+error: aborting due to 30 previous errors
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/lint/reasons-forbidden.rs b/src/test/ui/lint/reasons-forbidden.rs
index 19ab767..6a71176 100644
--- a/src/test/ui/lint/reasons-forbidden.rs
+++ b/src/test/ui/lint/reasons-forbidden.rs
@@ -3,6 +3,8 @@
 #![forbid(
     unsafe_code,
     //~^ NOTE `forbid` level set here
+    //~| NOTE `forbid` level set here
+    //~| NOTE `forbid` level set here
     reason = "our errors & omissions insurance policy doesn't cover unsafe Rust"
 )]
 
@@ -13,7 +15,13 @@
 
     #[allow(unsafe_code)]
     //~^ ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
+    //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
+    //~| ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code)
     //~| NOTE overruled by previous forbid
+    //~| NOTE overruled by previous forbid
+    //~| NOTE overruled by previous forbid
+    //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
+    //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
     //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust
     unsafe {
         *a_billion_dollar_mistake
diff --git a/src/test/ui/lint/reasons-forbidden.stderr b/src/test/ui/lint/reasons-forbidden.stderr
index ea09e59..0954ede 100644
--- a/src/test/ui/lint/reasons-forbidden.stderr
+++ b/src/test/ui/lint/reasons-forbidden.stderr
@@ -1,5 +1,5 @@
 error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
-  --> $DIR/reasons-forbidden.rs:14:13
+  --> $DIR/reasons-forbidden.rs:16:13
    |
 LL |     unsafe_code,
    |     ----------- `forbid` level set here
@@ -9,6 +9,28 @@
    |
    = note: our errors & omissions insurance policy doesn't cover unsafe Rust
 
-error: aborting due to previous error
+error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
+  --> $DIR/reasons-forbidden.rs:16:13
+   |
+LL |     unsafe_code,
+   |     ----------- `forbid` level set here
+...
+LL |     #[allow(unsafe_code)]
+   |             ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: our errors & omissions insurance policy doesn't cover unsafe Rust
+
+error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code)
+  --> $DIR/reasons-forbidden.rs:16:13
+   |
+LL |     unsafe_code,
+   |     ----------- `forbid` level set here
+...
+LL |     #[allow(unsafe_code)]
+   |             ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: our errors & omissions insurance policy doesn't cover unsafe Rust
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/reasons.rs b/src/test/ui/lint/reasons.rs
index fa9f012..4722e85 100644
--- a/src/test/ui/lint/reasons.rs
+++ b/src/test/ui/lint/reasons.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(lint_reasons)]
 
diff --git a/src/test/ui/lint/type-overflow.rs b/src/test/ui/lint/type-overflow.rs
index 79ffc82d..e40321e 100644
--- a/src/test/ui/lint/type-overflow.rs
+++ b/src/test/ui/lint/type-overflow.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![warn(overflowing_literals)]
 
 fn main() {
diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr
index bdb5959..169e77c 100644
--- a/src/test/ui/lint/uninitialized-zeroed.stderr
+++ b/src/test/ui/lint/uninitialized-zeroed.stderr
@@ -12,7 +12,7 @@
    |
 LL | #![deny(invalid_value)]
    |         ^^^^^^^^^^^^^
-   = note: References must be non-null
+   = note: references must be non-null
 
 error: the type `&'static T` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:30:32
@@ -23,7 +23,7 @@
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: References must be non-null
+   = note: references must be non-null
 
 error: the type `Wrap<&'static T>` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:32:38
@@ -34,7 +34,7 @@
    |                                      this code causes undefined behavior when executed
    |                                      help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: References must be non-null (in this struct field)
+note: references must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:18:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -49,7 +49,7 @@
    |                                      this code causes undefined behavior when executed
    |                                      help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: References must be non-null (in this struct field)
+note: references must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:18:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -64,7 +64,7 @@
    |                       this code causes undefined behavior when executed
    |                       help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: The never type (`!`) has no valid value
+   = note: the `!` type has no valid value
 
 error: the type `!` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:41:23
@@ -75,7 +75,7 @@
    |                       this code causes undefined behavior when executed
    |                       help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: The never type (`!`) has no valid value
+   = note: the `!` type has no valid value
 
 error: the type `(i32, !)` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:43:30
@@ -86,7 +86,7 @@
    |                              this code causes undefined behavior when executed
    |                              help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: The never type (`!`) has no valid value
+   = note: the `!` type has no valid value
 
 error: the type `(i32, !)` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:44:30
@@ -97,7 +97,7 @@
    |                              this code causes undefined behavior when executed
    |                              help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: The never type (`!`) has no valid value
+   = note: the `!` type has no valid value
 
 error: the type `Void` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:46:26
@@ -108,7 +108,7 @@
    |                          this code causes undefined behavior when executed
    |                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: 0-variant enums have no valid value
+   = note: enums with no variants have no valid value
 
 error: the type `Void` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:47:26
@@ -119,7 +119,7 @@
    |                          this code causes undefined behavior when executed
    |                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: 0-variant enums have no valid value
+   = note: enums with no variants have no valid value
 
 error: the type `&'static i32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:49:34
@@ -130,7 +130,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: References must be non-null
+   = note: references must be non-null
 
 error: the type `&'static i32` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:50:34
@@ -141,7 +141,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: References must be non-null
+   = note: references must be non-null
 
 error: the type `Ref` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:52:25
@@ -152,7 +152,7 @@
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: References must be non-null (in this struct field)
+note: references must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:15:12
    |
 LL | struct Ref(&'static i32);
@@ -167,7 +167,7 @@
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: References must be non-null (in this struct field)
+note: references must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:15:12
    |
 LL | struct Ref(&'static i32);
@@ -182,7 +182,7 @@
    |                          this code causes undefined behavior when executed
    |                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: Function pointers must be non-null
+   = note: function pointers must be non-null
 
 error: the type `fn()` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:56:26
@@ -193,7 +193,7 @@
    |                          this code causes undefined behavior when executed
    |                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: Function pointers must be non-null
+   = note: function pointers must be non-null
 
 error: the type `Wrap<fn()>` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:58:32
@@ -204,7 +204,7 @@
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: Function pointers must be non-null (in this struct field)
+note: function pointers must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:18:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -219,7 +219,7 @@
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: Function pointers must be non-null (in this struct field)
+note: function pointers must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:18:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -234,7 +234,7 @@
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: Function pointers must be non-null (in this enum field)
+note: function pointers must be non-null (in this enum field)
   --> $DIR/uninitialized-zeroed.rs:19:28
    |
 LL | enum WrapEnum<T> { Wrapped(T) }
@@ -249,7 +249,7 @@
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: Function pointers must be non-null (in this enum field)
+note: function pointers must be non-null (in this enum field)
   --> $DIR/uninitialized-zeroed.rs:19:28
    |
 LL | enum WrapEnum<T> { Wrapped(T) }
@@ -264,7 +264,7 @@
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: References must be non-null (in this struct field)
+note: references must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:16:16
    |
 LL | struct RefPair((&'static i32, i32));
@@ -279,7 +279,7 @@
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: References must be non-null (in this struct field)
+note: references must be non-null (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:16:16
    |
 LL | struct RefPair((&'static i32, i32));
@@ -294,7 +294,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: std::ptr::NonNull<i32> must be non-null
+   = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `std::ptr::NonNull<i32>` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:68:34
@@ -305,7 +305,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: std::ptr::NonNull<i32> must be non-null
+   = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `*const dyn std::marker::Send` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:70:37
@@ -316,7 +316,7 @@
    |                                     this code causes undefined behavior when executed
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: The vtable of a wide raw pointer must be non-null
+   = note: the vtable of a wide raw pointer must be non-null
 
 error: the type `*const dyn std::marker::Send` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:71:37
@@ -327,7 +327,7 @@
    |                                     this code causes undefined behavior when executed
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: The vtable of a wide raw pointer must be non-null
+   = note: the vtable of a wide raw pointer must be non-null
 
 error: the type `bool` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:75:26
@@ -338,7 +338,7 @@
    |                          this code causes undefined behavior when executed
    |                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: Booleans must be `true` or `false`
+   = note: booleans must be either `true` or `false`
 
 error: the type `Wrap<char>` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:78:32
@@ -349,7 +349,7 @@
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: Characters must be a valid unicode codepoint (in this struct field)
+note: characters must be a valid Unicode codepoint (in this struct field)
   --> $DIR/uninitialized-zeroed.rs:18:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -364,7 +364,7 @@
    |                            this code causes undefined behavior when executed
    |                            help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: NonBig must be initialized inside its custom valid range
+   = note: `NonBig` must be initialized inside its custom valid range
 
 error: the type `&'static i32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:84:34
@@ -375,7 +375,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: References must be non-null
+   = note: references must be non-null
 
 error: the type `&'static [i32]` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:85:36
@@ -386,7 +386,7 @@
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: References must be non-null
+   = note: references must be non-null
 
 error: the type `std::num::NonZeroU32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:86:32
@@ -397,7 +397,7 @@
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: std::num::NonZeroU32 must be non-null
+   = note: `std::num::NonZeroU32` must be non-null
 
 error: the type `std::ptr::NonNull<i32>` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:89:34
@@ -408,7 +408,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: std::ptr::NonNull<i32> must be non-null
+   = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `std::ptr::NonNull<i32>` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:90:34
@@ -419,7 +419,7 @@
    |                                  this code causes undefined behavior when executed
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: std::ptr::NonNull<i32> must be non-null
+   = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `bool` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:91:26
@@ -430,7 +430,7 @@
    |                          this code causes undefined behavior when executed
    |                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: Booleans must be `true` or `false`
+   = note: booleans must be either `true` or `false`
 
 error: aborting due to 35 previous errors
 
diff --git a/src/test/ui/lint/unused_labels.rs b/src/test/ui/lint/unused_labels.rs
index d234a2f..8a3568f 100644
--- a/src/test/ui/lint/unused_labels.rs
+++ b/src/test/ui/lint/unused_labels.rs
@@ -2,7 +2,7 @@
 // should also deal with the edge cases where a label is shadowed,
 // within nested loops
 
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(label_break_value)]
 #![warn(unused_labels)]
diff --git a/src/test/ui/lint/use-redundant.rs b/src/test/ui/lint/use-redundant.rs
index 3b00424..53315dc 100644
--- a/src/test/ui/lint/use-redundant.rs
+++ b/src/test/ui/lint/use-redundant.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![warn(unused_imports)]
 
 use crate::foo::Bar;
diff --git a/src/test/ui/macros/builtin-std-paths-fail.rs b/src/test/ui/macros/builtin-std-paths-fail.rs
index 33de3d5..c1a4e32 100644
--- a/src/test/ui/macros/builtin-std-paths-fail.rs
+++ b/src/test/ui/macros/builtin-std-paths-fail.rs
@@ -1,6 +1,8 @@
 #[derive(
     core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core`
+                          //~| ERROR could not find `RustcDecodable` in `core`
     core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core`
+                          //~| ERROR could not find `RustcDecodable` in `core`
 )]
 #[core::bench] //~ ERROR could not find `bench` in `core`
 #[core::global_allocator] //~ ERROR could not find `global_allocator` in `core`
@@ -10,7 +12,9 @@
 
 #[derive(
     std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std`
+                         //~| ERROR could not find `RustcDecodable` in `std`
     std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std`
+                         //~| ERROR could not find `RustcDecodable` in `std`
 )]
 #[std::bench] //~ ERROR could not find `bench` in `std`
 #[std::global_allocator] //~ ERROR could not find `global_allocator` in `std`
diff --git a/src/test/ui/macros/builtin-std-paths-fail.stderr b/src/test/ui/macros/builtin-std-paths-fail.stderr
index 6de6890..9831e46 100644
--- a/src/test/ui/macros/builtin-std-paths-fail.stderr
+++ b/src/test/ui/macros/builtin-std-paths-fail.stderr
@@ -1,23 +1,23 @@
 error[E0433]: failed to resolve: could not find `bench` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:5:9
+  --> $DIR/builtin-std-paths-fail.rs:7:9
    |
 LL | #[core::bench]
    |         ^^^^^ could not find `bench` in `core`
 
 error[E0433]: failed to resolve: could not find `global_allocator` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:6:9
+  --> $DIR/builtin-std-paths-fail.rs:8:9
    |
 LL | #[core::global_allocator]
    |         ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `core`
 
 error[E0433]: failed to resolve: could not find `test_case` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:7:9
+  --> $DIR/builtin-std-paths-fail.rs:9:9
    |
 LL | #[core::test_case]
    |         ^^^^^^^^^ could not find `test_case` in `core`
 
 error[E0433]: failed to resolve: could not find `test` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:8:9
+  --> $DIR/builtin-std-paths-fail.rs:10:9
    |
 LL | #[core::test]
    |         ^^^^ could not find `test` in `core`
@@ -29,47 +29,71 @@
    |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
-  --> $DIR/builtin-std-paths-fail.rs:3:11
+  --> $DIR/builtin-std-paths-fail.rs:4:11
+   |
+LL |     core::RustcDecodable,
+   |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
+
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
+  --> $DIR/builtin-std-paths-fail.rs:4:11
+   |
+LL |     core::RustcDecodable,
+   |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
+
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
+  --> $DIR/builtin-std-paths-fail.rs:2:11
    |
 LL |     core::RustcDecodable,
    |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
 
 error[E0433]: failed to resolve: could not find `bench` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:15:8
+  --> $DIR/builtin-std-paths-fail.rs:19:8
    |
 LL | #[std::bench]
    |        ^^^^^ could not find `bench` in `std`
 
 error[E0433]: failed to resolve: could not find `global_allocator` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:16:8
+  --> $DIR/builtin-std-paths-fail.rs:20:8
    |
 LL | #[std::global_allocator]
    |        ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `std`
 
 error[E0433]: failed to resolve: could not find `test_case` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:17:8
+  --> $DIR/builtin-std-paths-fail.rs:21:8
    |
 LL | #[std::test_case]
    |        ^^^^^^^^^ could not find `test_case` in `std`
 
 error[E0433]: failed to resolve: could not find `test` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:18:8
+  --> $DIR/builtin-std-paths-fail.rs:22:8
    |
 LL | #[std::test]
    |        ^^^^ could not find `test` in `std`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:12:10
+  --> $DIR/builtin-std-paths-fail.rs:14:10
    |
 LL |     std::RustcDecodable,
    |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
-  --> $DIR/builtin-std-paths-fail.rs:13:10
+  --> $DIR/builtin-std-paths-fail.rs:16:10
    |
 LL |     std::RustcDecodable,
    |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
 
-error: aborting due to 12 previous errors
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
+  --> $DIR/builtin-std-paths-fail.rs:16:10
+   |
+LL |     std::RustcDecodable,
+   |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
+
+error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
+  --> $DIR/builtin-std-paths-fail.rs:14:10
+   |
+LL |     std::RustcDecodable,
+   |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
+
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/issue-68058.rs b/src/test/ui/macros/issue-68058.rs
new file mode 100644
index 0000000..24da262
--- /dev/null
+++ b/src/test/ui/macros/issue-68058.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+macro_rules! foo {
+    ($doc: expr) => {
+        fn f() {
+            #[doc = $doc]
+            ()
+        }
+    };
+}
+
+foo!("doc");
+
+fn main() {}
diff --git a/src/test/ui/macros/macro-local-data-key-priv.stderr b/src/test/ui/macros/macro-local-data-key-priv.stderr
index 9b44421..72994d1 100644
--- a/src/test/ui/macros/macro-local-data-key-priv.stderr
+++ b/src/test/ui/macros/macro-local-data-key-priv.stderr
@@ -2,7 +2,14 @@
   --> $DIR/macro-local-data-key-priv.rs:8:10
    |
 LL |     bar::baz.with(|_| ());
-   |          ^^^
+   |          ^^^ this constant is private
+   |
+note: the constant `baz` is defined here
+  --> $DIR/macro-local-data-key-priv.rs:4:5
+   |
+LL |     thread_local!(static baz: f64 = 0.0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-name-typo.rs b/src/test/ui/macros/macro-name-typo.rs
index 1ddc419..b2892f3 100644
--- a/src/test/ui/macros/macro-name-typo.rs
+++ b/src/test/ui/macros/macro-name-typo.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 fn main() {
     printlx!("oh noes!"); //~ ERROR cannot find
 }
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index ce2e198..00afbde 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -1,8 +1,13 @@
 error: cannot find macro `printlx` in this scope
-  --> $DIR/macro-name-typo.rs:2:5
+  --> $DIR/macro-name-typo.rs:6:5
    |
 LL |     printlx!("oh noes!");
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+   | 
+  ::: $SRC_DIR/libstd/macros.rs:LL:COL
+   |
+LL | macro_rules! println {
+   | -------------------- similarly named macro `println` defined here
 
 error: aborting due to previous error
 
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 68eb350..3c3948c 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,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 fn main() {
     inline!(); //~ ERROR cannot find macro `inline` in this scope
 }
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index ec00760..5364590 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -1,8 +1,13 @@
 error: cannot find macro `inline` in this scope
-  --> $DIR/macro-path-prelude-fail-3.rs:2:5
+  --> $DIR/macro-path-prelude-fail-3.rs:6:5
    |
 LL |     inline!();
    |     ^^^^^^ help: a macro with a similar name exists: `line`
+   | 
+  ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
+   |
+LL |     macro_rules! line {
+   |     ----------------- similarly named macro `line` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr
index 8b4e90a..74fb519 100644
--- a/src/test/ui/macros/macro-use-wrong-name.stderr
+++ b/src/test/ui/macros/macro-use-wrong-name.stderr
@@ -3,6 +3,11 @@
    |
 LL |     macro_two!();
    |     ^^^^^^^^^ help: a macro with a similar name exists: `macro_one`
+   | 
+  ::: $DIR/auxiliary/two_macros.rs:2:1
+   |
+LL | macro_rules! macro_one { () => ("one") }
+   | ---------------------- similarly named macro `macro_one` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/meta-item-absolute-path.rs b/src/test/ui/macros/meta-item-absolute-path.rs
index 14d23be..8ed911c 100644
--- a/src/test/ui/macros/meta-item-absolute-path.rs
+++ b/src/test/ui/macros/meta-item-absolute-path.rs
@@ -1,4 +1,5 @@
 #[derive(::Absolute)] //~ ERROR failed to resolve
+                      //~| ERROR failed to resolve
 struct S;
 
 fn main() {}
diff --git a/src/test/ui/macros/meta-item-absolute-path.stderr b/src/test/ui/macros/meta-item-absolute-path.stderr
index 711fa4d..c53971e 100644
--- a/src/test/ui/macros/meta-item-absolute-path.stderr
+++ b/src/test/ui/macros/meta-item-absolute-path.stderr
@@ -4,6 +4,12 @@
 LL | #[derive(::Absolute)]
    |            ^^^^^^^^ maybe a missing crate `Absolute`?
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: maybe a missing crate `Absolute`?
+  --> $DIR/meta-item-absolute-path.rs:1:12
+   |
+LL | #[derive(::Absolute)]
+   |            ^^^^^^^^ maybe a missing crate `Absolute`?
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/malformed/malformed-interpolated.stderr b/src/test/ui/malformed/malformed-interpolated.stderr
index bcd2ef54..6f6ad45 100644
--- a/src/test/ui/malformed/malformed-interpolated.stderr
+++ b/src/test/ui/malformed/malformed-interpolated.stderr
@@ -4,7 +4,7 @@
 LL | check!(0u8);
    |        ^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: unexpected token: `-0`
   --> $DIR/malformed-interpolated.rs:5:25
diff --git a/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs b/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs
new file mode 100644
index 0000000..0af7066
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs
@@ -0,0 +1,17 @@
+// check-pass
+// Regression test for issue #61651
+// Verifies that we don't try to constrain inference
+// variables due to the presence of multiple applicable
+// marker trait impls
+
+#![feature(marker_trait_attr)]
+
+#[marker] // Remove this line and it works?!?
+trait Foo<T> {}
+impl Foo<u16> for u8 {}
+impl Foo<[u8; 1]> for u8 {}
+fn foo<T: Foo<U>, U>(_: T) -> U { unimplemented!() }
+
+fn main() {
+    let _: u16 = foo(0_u8);
+}
diff --git a/src/test/ui/match/match-range-fail-2.rs b/src/test/ui/match/match-range-fail-2.rs
index 19e6e12..792664e 100644
--- a/src/test/ui/match/match-range-fail-2.rs
+++ b/src/test/ui/match/match-range-fail-2.rs
@@ -6,16 +6,19 @@
         _ => { }
     };
     //~^^^ ERROR lower range bound must be less than or equal to upper
+    //~| ERROR lower range bound must be less than or equal to upper
 
     match 5 {
         0 .. 0 => { }
         _ => { }
     };
     //~^^^ ERROR lower range bound must be less than upper
+    //~| ERROR lower range bound must be less than upper
 
     match 5u64 {
         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
         _ => { }
     };
     //~^^^ ERROR lower range bound must be less than or equal to upper
+    //~| ERROR lower range bound must be less than or equal to upper
 }
diff --git a/src/test/ui/match/match-range-fail-2.stderr b/src/test/ui/match/match-range-fail-2.stderr
index 52a2bf2..7a0852d 100644
--- a/src/test/ui/match/match-range-fail-2.stderr
+++ b/src/test/ui/match/match-range-fail-2.stderr
@@ -5,18 +5,36 @@
    |         ^ lower bound larger than upper bound
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/match-range-fail-2.rs:11:9
+  --> $DIR/match-range-fail-2.rs:12:9
    |
 LL |         0 .. 0 => { }
    |         ^
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:17:9
+  --> $DIR/match-range-fail-2.rs:19:9
    |
 LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
    |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
 
-error: aborting due to 3 previous errors
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/match-range-fail-2.rs:5:9
+   |
+LL |         6 ..= 1 => { }
+   |         ^ lower bound larger than upper bound
+
+error[E0579]: lower range bound must be less than upper
+  --> $DIR/match-range-fail-2.rs:12:9
+   |
+LL |         0 .. 0 => { }
+   |         ^
+
+error[E0030]: lower range bound must be less than or equal to upper
+  --> $DIR/match-range-fail-2.rs:19:9
+   |
+LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
+   |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
+
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0030, E0579.
 For more information about an error, try `rustc --explain E0030`.
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
index e0dec0a..5ff4b41 100644
--- a/src/test/ui/methods/method-call-err-msg.rs
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -15,6 +15,6 @@
 
     let y = Foo;
     y.zero()
-     .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
+     .take()    //~ ERROR no method named `take` found
      .one(0);
 }
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index 94c27b7..7efdd91 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -25,7 +25,7 @@
 LL |      .two(0);
    |       ^^^ expected 2 parameters
 
-error[E0599]: no method named `take` found for type `Foo` in the current scope
+error[E0599]: no method named `take` found for struct `Foo` in the current scope
   --> $DIR/method-call-err-msg.rs:18:7
    |
 LL | pub struct Foo;
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
index 67fd8d7..c9f235c 100644
--- a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -1,6 +1,8 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
    |
+LL | fn main() {
+   |        - help: consider introducing lifetime `'a` here: `<'a>`
 LL |     0.clone::<'a>();
    |               ^^ undeclared lifetime
 
diff --git a/src/test/ui/mir/issue-67947.rs b/src/test/ui/mir/issue-67947.rs
new file mode 100644
index 0000000..79e75e6
--- /dev/null
+++ b/src/test/ui/mir/issue-67947.rs
@@ -0,0 +1,7 @@
+struct Bug {
+    A: [(); { *"" }.len()],
+    //~^ ERROR: cannot move a value of type str
+    //~| ERROR: cannot move out of a shared reference
+}
+
+fn main() {}
diff --git a/src/test/ui/mir/issue-67947.stderr b/src/test/ui/mir/issue-67947.stderr
new file mode 100644
index 0000000..d526218
--- /dev/null
+++ b/src/test/ui/mir/issue-67947.stderr
@@ -0,0 +1,16 @@
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/issue-67947.rs:2:13
+   |
+LL |     A: [(); { *"" }.len()],
+   |             ^^^^^^^
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/issue-67947.rs:2:15
+   |
+LL |     A: [(); { *"" }.len()],
+   |               ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index da018aa..f8d677b 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `count` found for type `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
+error[E0599]: no method named `count` found for struct `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
index 83cea16..58ceaff 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs
@@ -3,5 +3,5 @@
 fn main() {
     let a: Result<(), Foo> = Ok(());
     a.unwrap();
-    //~^ ERROR no method named `unwrap` found for type `std::result::Result<(), Foo>`
+    //~^ ERROR no method named `unwrap` found
 }
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 865092e..bbfb000 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `unwrap` found for type `std::result::Result<(), Foo>` in the current scope
+error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope
   --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
diff --git a/src/test/ui/module-macro_use-arguments.rs b/src/test/ui/module-macro_use-arguments.rs
index 6627b48..121b492 100644
--- a/src/test/ui/module-macro_use-arguments.rs
+++ b/src/test/ui/module-macro_use-arguments.rs
@@ -1,4 +1,4 @@
-#[macro_use(foo, bar)] //~ ERROR arguments to macro_use are not allowed here
+#[macro_use(foo, bar)] //~ ERROR arguments to `macro_use` are not allowed here
 mod foo {
 }
 
diff --git a/src/test/ui/module-macro_use-arguments.stderr b/src/test/ui/module-macro_use-arguments.stderr
index 2a75736..af799cb 100644
--- a/src/test/ui/module-macro_use-arguments.stderr
+++ b/src/test/ui/module-macro_use-arguments.stderr
@@ -1,4 +1,4 @@
-error: arguments to macro_use are not allowed here
+error: arguments to `macro_use` are not allowed here
   --> $DIR/module-macro_use-arguments.rs:1:1
    |
 LL | #[macro_use(foo, bar)]
diff --git a/src/test/ui/moves/move-out-of-array-ref.rs b/src/test/ui/moves/move-out-of-array-ref.rs
index 4ca60dd..343f00f 100644
--- a/src/test/ui/moves/move-out-of-array-ref.rs
+++ b/src/test/ui/moves/move-out-of-array-ref.rs
@@ -1,7 +1,5 @@
 // Ensure that we cannot move out of a reference to a fixed-size array
 
-#![feature(slice_patterns)]
-
 struct D { _x: u8 }
 
 impl Drop for D { fn drop(&mut self) { } }
diff --git a/src/test/ui/moves/move-out-of-array-ref.stderr b/src/test/ui/moves/move-out-of-array-ref.stderr
index ae3d2f5..fd682e5 100644
--- a/src/test/ui/moves/move-out-of-array-ref.stderr
+++ b/src/test/ui/moves/move-out-of-array-ref.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:10:24
+  --> $DIR/move-out-of-array-ref.rs:8:24
    |
 LL |     let [_, e, _, _] = *a;
    |             -          ^^
@@ -10,7 +10,7 @@
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:15:27
+  --> $DIR/move-out-of-array-ref.rs:13:27
    |
 LL |     let [_, s @ .. , _] = *a;
    |             ------        ^^
@@ -21,7 +21,7 @@
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:20:24
+  --> $DIR/move-out-of-array-ref.rs:18:24
    |
 LL |     let [_, e, _, _] = *a;
    |             -          ^^
@@ -32,7 +32,7 @@
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:25:27
+  --> $DIR/move-out-of-array-ref.rs:23:27
    |
 LL |     let [_, s @ .. , _] = *a;
    |             ------        ^^
diff --git a/src/test/ui/multi-panic.rs b/src/test/ui/multi-panic.rs
index e4b41e4..0f8bddf 100644
--- a/src/test/ui/multi-panic.rs
+++ b/src/test/ui/multi-panic.rs
@@ -10,7 +10,7 @@
 
     assert_eq!(it.next().map(|l| l.starts_with("thread '<unnamed>' panicked at")), Some(true));
     assert_eq!(it.next(), Some("note: run with `RUST_BACKTRACE=1` \
-                                environment variable to display a backtrace."));
+                                environment variable to display a backtrace"));
     assert_eq!(it.next().map(|l| l.starts_with("thread 'main' panicked at")), Some(true));
     assert_eq!(it.next(), None);
 }
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index 0484661..13d727d 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -24,6 +24,11 @@
    |
 LL |     check(xm1::S);
    |           ^^^^^^
+   | 
+  ::: $DIR/auxiliary/namespace-mix.rs:3:5
+   |
+LL |     pub struct TS();
+   |     ---------------- similarly named tuple struct `TS` defined here
    |
    = note: can't use a type alias as a constructor
 help: a tuple struct with a similar name exists
@@ -64,6 +69,11 @@
    |
 LL |     check(xm7::V);
    |           ^^^^^^ did you mean `xm7::V { /* fields */ }`?
+   | 
+  ::: $DIR/auxiliary/namespace-mix.rs:7:9
+   |
+LL |         TV(),
+   |         ---- similarly named tuple variant `TV` defined here
    |
 help: a tuple variant with a similar name exists
    |
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
index 837e90d..77288f1 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -3,8 +3,12 @@
    |
 LL | fn should_ret_unit() -> impl T {
    |                         ^^^^^^ the trait `T` is not implemented for `()`
+LL |
+LL |     panic!()
+   |     -------- this returned value is of type `()`
    |
    = note: the return type of a function must have a statically known size
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/never_type/issue-2149.rs b/src/test/ui/never_type/issue-2149.rs
index d46f0e6..d6426d2 100644
--- a/src/test/ui/never_type/issue-2149.rs
+++ b/src/test/ui/never_type/issue-2149.rs
@@ -11,5 +11,5 @@
 }
 fn main() {
     ["hi"].bind(|x| [x] );
-    //~^ ERROR no method named `bind` found for type `[&str; 1]` in the current scope
+    //~^ ERROR no method named `bind` found
 }
diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr
index 8ce2ba0..9645244 100644
--- a/src/test/ui/never_type/issue-2149.stderr
+++ b/src/test/ui/never_type/issue-2149.stderr
@@ -6,7 +6,7 @@
    |
    = help: the trait `std::ops::Add<std::vec::Vec<B>>` is not implemented for `()`
 
-error[E0599]: no method named `bind` found for type `[&str; 1]` in the current scope
+error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope
   --> $DIR/issue-2149.rs:13:12
    |
 LL |     ["hi"].bind(|x| [x] );
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 3d79ff0..b4e18c2 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/escape-argument-callee.rs:26:38
    |
 LL |         let mut closure = expect_sig(|p, y| *p = y);
@@ -18,7 +18,7 @@
    |                                       |  has type `&'1 i32`
    |                                       has type `&'_#2r mut &'2 i32`
 
-note: No external requirements
+note: no external requirements
   --> $DIR/escape-argument-callee.rs:20:1
    |
 LL | / fn test() {
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index 37f04af..533a17b 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/escape-argument.rs:26:38
    |
 LL |         let mut closure = expect_sig(|p, y| *p = y);
@@ -9,7 +9,7 @@
                for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)),
            ]
 
-note: No external requirements
+note: no external requirements
   --> $DIR/escape-argument.rs:20:1
    |
 LL | / fn test() {
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
index 810c028..60d0206 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/escape-upvar-nested.rs:21:32
    |
 LL |             let mut closure1 = || p = &y;
@@ -13,7 +13,7 @@
    = note: number of external vids: 4
    = note: where '_#1r: '_#3r
 
-note: External requirements
+note: external requirements
   --> $DIR/escape-upvar-nested.rs:20:27
    |
 LL |           let mut closure = || {
@@ -32,7 +32,7 @@
    = note: number of external vids: 4
    = note: where '_#1r: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/escape-upvar-nested.rs:13:1
    |
 LL | / fn test() {
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
index bf04276..f64ccf1 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/escape-upvar-ref.rs:23:27
    |
 LL |         let mut closure = || p = &y;
@@ -13,7 +13,7 @@
    = note: number of external vids: 4
    = note: where '_#1r: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/escape-upvar-ref.rs:17:1
    |
 LL | / fn test() {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 4e3aa35..e1e0cdc 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-fail-no-postdom.rs:43:9
    |
 LL | /         |_outlives1, _outlives2, _outlives3, x, y| {
@@ -27,7 +27,7 @@
 LL |             demand_y(x, y, p)
    |             ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1
    |
 LL | / fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index cd61b8b..b653502 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/propagate-approximated-ref.rs:43:47
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
@@ -18,7 +18,7 @@
    = note: number of external vids: 5
    = note: where '_#1r: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-ref.rs:42:1
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 259140c..708e50d 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:21:15
    |
 LL |       foo(cell, |cell_a, cell_x| {
@@ -23,7 +23,7 @@
 LL |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:18:1
    |
 LL | / fn case1() {
@@ -37,7 +37,7 @@
    |
    = note: defining type: case1
 
-note: External requirements
+note: external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15
    |
 LL |       foo(cell, |cell_a, cell_x| {
@@ -53,7 +53,7 @@
    = note: number of external vids: 2
    = note: where '_#1r: '_#0r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1
    |
 LL | / fn case2() {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index b3dd682..17d33e8 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:47
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
@@ -19,7 +19,7 @@
    = note: number of external vids: 4
    = note: where '_#1r: '_#0r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:31:1
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index ab12d08..5dce8d0 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:47
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
@@ -19,7 +19,7 @@
    = note: number of external vids: 5
    = note: where '_#1r: '_#0r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:34:1
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index b2209e9..5c5d510 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/propagate-approximated-val.rs:36:45
    |
 LL |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
@@ -18,7 +18,7 @@
    = note: number of external vids: 5
    = note: where '_#1r: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-approximated-val.rs:35:1
    |
 LL | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
index 1df7c61..ac182be 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
@@ -4,7 +4,7 @@
 // regions is erased.
 
 // compile-flags:-Zborrowck=mir -Zverbose
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index 55ee515..c111e65 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/propagate-despite-same-free-region.rs:42:9
    |
 LL | /         |_outlives1, _outlives2, x, y| {
@@ -16,7 +16,7 @@
    = note: number of external vids: 4
    = note: where '_#1r: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-despite-same-free-region.rs:39:1
    |
 LL | / fn supply<'a>(cell_a: Cell<&'a u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 1c29af8..52df46e 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:35:47
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
@@ -27,7 +27,7 @@
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index afa0e9f..0270cc4 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:39:47
    |
 LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
@@ -27,7 +27,7 @@
 LL |         demand_y(x, y, x.get())
    |         ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1
    |
 LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
index 0dbb530..5317bb6 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/propagate-from-trait-match.rs:32:36
    |
 LL |       establish_relationships(value, |value| {
@@ -18,7 +18,7 @@
    = note: number of external vids: 2
    = note: where T: '_#1r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/propagate-from-trait-match.rs:28:1
    |
 LL | / fn supply<'a, T>(value: T)
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index ca794d9..79ed150 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/return-wrong-bound-region.rs:11:16
    |
 LL |     expect_sig(|a, b| b); // ought to return `a`
@@ -18,7 +18,7 @@
    |                 |  has type `&'1 i32`
    |                 has type `&'2 i32`
 
-note: No external requirements
+note: no external requirements
   --> $DIR/return-wrong-bound-region.rs:10:1
    |
 LL | / fn test() {
diff --git a/src/test/ui/nll/constant.rs b/src/test/ui/nll/constant.rs
index b1ea2c9..039b6aa 100644
--- a/src/test/ui/nll/constant.rs
+++ b/src/test/ui/nll/constant.rs
@@ -2,7 +2,7 @@
 // arbitrary types without ICEs.
 
 // compile-flags:-Zborrowck=mir
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 const HI: &str = "hi";
 
diff --git a/src/test/ui/nll/drop-may-dangle.rs b/src/test/ui/nll/drop-may-dangle.rs
index 0f3d27d..1897589 100644
--- a/src/test/ui/nll/drop-may-dangle.rs
+++ b/src/test/ui/nll/drop-may-dangle.rs
@@ -3,7 +3,7 @@
 // including) the call to `use_x`. The `else` branch is not included.
 
 // compile-flags:-Zborrowck=mir
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(warnings)]
 #![feature(dropck_eyepatch)]
diff --git a/src/test/ui/nll/extra-unused-mut.rs b/src/test/ui/nll/extra-unused-mut.rs
index e9c8df4..db056a22 100644
--- a/src/test/ui/nll/extra-unused-mut.rs
+++ b/src/test/ui/nll/extra-unused-mut.rs
@@ -1,6 +1,6 @@
 // extra unused mut lint tests for #51918
 
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(generators, nll)]
 #![deny(unused_mut)]
diff --git a/src/test/ui/nll/generator-distinct-lifetime.rs b/src/test/ui/nll/generator-distinct-lifetime.rs
index 1bd39db..3102562 100644
--- a/src/test/ui/nll/generator-distinct-lifetime.rs
+++ b/src/test/ui/nll/generator-distinct-lifetime.rs
@@ -6,7 +6,7 @@
 // over a yield -- because the data that is borrowed (`*x`) is not
 // stored on the stack.
 
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 fn foo(x: &mut u32) {
     move || {
diff --git a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
index 72212e9..e814794 100644
--- a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Zborrowck=mir
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/projection-return.rs b/src/test/ui/nll/projection-return.rs
index 5c34043..017f53d 100644
--- a/src/test/ui/nll/projection-return.rs
+++ b/src/test/ui/nll/projection-return.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Zborrowck=mir
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs b/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
index 1bbc896..527cca1 100644
--- a/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
+++ b/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
@@ -6,7 +6,7 @@
 // another -- effectively, the single lifetime `'a` is just inferred
 // to be the intersection of the two distinct lifetimes.
 //
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // compile-flags:-Zno-leak-check
 
 #![feature(nll)]
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
index 4e8599b..3a46188 100644
--- a/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
+++ b/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
@@ -2,7 +2,7 @@
 // function returning always its first argument can be upcast to one
 // that returns either first or second argument.
 //
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // compile-flags:-Zno-leak-check
 
 #![feature(nll)]
diff --git a/src/test/ui/nll/ty-outlives/projection-body.rs b/src/test/ui/nll/ty-outlives/projection-body.rs
index 148120d..b03a539 100644
--- a/src/test/ui/nll/ty-outlives/projection-body.rs
+++ b/src/test/ui/nll/ty-outlives/projection-body.rs
@@ -1,7 +1,7 @@
 // Test that when we infer the lifetime to a subset of the fn body, it
 // works out.
 //
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 trait MyTrait<'a> {
     type Output;
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index c825227..bff8c66 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/projection-no-regions-closure.rs:25:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
@@ -11,7 +11,7 @@
    = note: number of external vids: 3
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-no-regions-closure.rs:21:1
    |
 LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
@@ -33,7 +33,7 @@
    |
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-no-regions-closure.rs:34:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
@@ -46,7 +46,7 @@
    = note: number of external vids: 3
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-no-regions-closure.rs:30:1
    |
 LL | / fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
@@ -59,7 +59,7 @@
    |
    = note: defining type: correct_region::<'_#1r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-no-regions-closure.rs:42:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
@@ -72,7 +72,7 @@
    = note: number of external vids: 4
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-no-regions-closure.rs:38:1
    |
 LL | / fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
@@ -94,7 +94,7 @@
    |
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-no-regions-closure.rs:52:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
@@ -107,7 +107,7 @@
    = note: number of external vids: 4
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-no-regions-closure.rs:47:1
    |
 LL | / fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index 7226c52..6d1fbcb 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-closure.rs:45:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -13,7 +13,7 @@
    = note: where T: '_#2r
    = note: where '_#1r: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-closure.rs:41:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -48,7 +48,7 @@
    |
    = help: consider adding the following bound: `'b: 'a`
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-closure.rs:56:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -62,7 +62,7 @@
    = note: where T: '_#3r
    = note: where '_#2r: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-closure.rs:51:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -97,7 +97,7 @@
    |
    = help: consider adding the following bound: `'b: 'a`
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-closure.rs:70:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -110,7 +110,7 @@
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#2r)>>::AssocType: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-closure.rs:62:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -124,7 +124,7 @@
    |
    = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-closure.rs:80:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -138,7 +138,7 @@
    = note: where T: '_#3r
    = note: where '_#2r: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-closure.rs:74:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 655995c..59d8aa4 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:37:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -12,7 +12,7 @@
    = note: number of external vids: 4
    = note: where '_#1r: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:33:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -39,7 +39,7 @@
    |
    = help: consider adding the following bound: `'b: 'a`
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -52,7 +52,7 @@
    = note: number of external vids: 4
    = note: where '_#2r: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:42:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -79,7 +79,7 @@
    |
    = help: consider adding the following bound: `'b: 'a`
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:60:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -92,7 +92,7 @@
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#2r)>>::AssocType: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:52:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -106,7 +106,7 @@
    |
    = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:69:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -119,7 +119,7 @@
    = note: number of external vids: 4
    = note: where '_#2r: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:64:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -133,7 +133,7 @@
    |
    = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:81:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -146,7 +146,7 @@
    = note: number of external vids: 3
    = note: where '_#1r: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:73:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
index b9c9611..be1b653 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
@@ -3,7 +3,7 @@
 // we don't even propagate constraints from the closures to the callers.
 
 // compile-flags:-Zborrowck=mir -Zverbose
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
index 2fb07b9..c3b9245 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -1,4 +1,4 @@
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:36:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -10,7 +10,7 @@
            ]
    = note: late-bound region is '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:32:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -23,7 +23,7 @@
    |
    = note: defining type: no_relationships_late::<'_#1r, T>
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -34,7 +34,7 @@
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:40:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -48,7 +48,7 @@
    |
    = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -59,7 +59,7 @@
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:49:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -73,7 +73,7 @@
    |
    = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -84,7 +84,7 @@
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:68:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -98,7 +98,7 @@
    |
    = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -109,7 +109,7 @@
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:77:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 501a55e3..1bd97c1 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:38:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -12,7 +12,7 @@
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:34:1
    |
 LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
@@ -34,7 +34,7 @@
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0:17 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(DefId(0:18 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::'a[0]), 'a))`...
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -47,7 +47,7 @@
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:43:1
    |
 LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
@@ -69,7 +69,7 @@
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReEarlyBound(0, 'a)`...
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:61:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -82,7 +82,7 @@
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:53:1
    |
 LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
@@ -96,7 +96,7 @@
    |
    = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:70:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -109,7 +109,7 @@
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:65:1
    |
 LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
@@ -123,7 +123,7 @@
    |
    = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:79:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -136,7 +136,7 @@
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:74:1
    |
 LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
@@ -150,7 +150,7 @@
    |
    = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -164,7 +164,7 @@
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:83:1
    |
 LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -191,7 +191,7 @@
    |
    = help: consider adding the following bound: `'b: 'a`
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:97:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -204,7 +204,7 @@
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:92:1
    |
 LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -218,7 +218,7 @@
    |
    = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
@@ -231,7 +231,7 @@
    = note: number of external vids: 3
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:101:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
index 4613dd2..a411162 100644
--- a/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
@@ -4,7 +4,7 @@
 //
 // Regression test for #53121.
 //
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 trait MyTrait<'a> {
     type Output;
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
index 89328c2..8d0c10a 100644
--- a/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
@@ -4,7 +4,7 @@
 // MyTrait<'a>>::Output: 'a` outlives `'a` (because the trait says
 // so).
 //
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 trait MyTrait<'a> {
     type Output: 'a;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index db0bca1..a213f42 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:24:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
@@ -11,7 +11,7 @@
    = note: number of external vids: 2
    = note: where T: '_#1r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:22:1
    |
 LL | / fn generic<T>(value: T) {
@@ -22,7 +22,7 @@
    |
    = note: defining type: generic::<T>
 
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
@@ -36,7 +36,7 @@
    = note: number of external vids: 3
    = note: where T: '_#1r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:28:1
    |
 LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 0021d73..a488637 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
    |
 LL |     with_signature(x, |y| y)
@@ -11,7 +11,7 @@
    = note: number of external vids: 3
    = note: where T: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:15:1
    |
 LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 46fef8e..62dfe94 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -1,4 +1,4 @@
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
    |
 LL |       with_signature(a, b, |x, y| {
@@ -19,7 +19,7 @@
    = note: number of external vids: 3
    = note: where T: '_#1r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:26:1
    |
 LL | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
@@ -48,7 +48,7 @@
    |
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:11 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(DefId(0:12 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::'a[0]), 'a))`...
 
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
    |
 LL |       with_signature(a, b, |x, y| {
@@ -68,7 +68,7 @@
    = note: number of external vids: 3
    = note: where T: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1
    |
 LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
@@ -82,7 +82,7 @@
    |
    = note: defining type: correct_region::<'_#1r, T>
 
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
    |
 LL |       with_signature(a, b, |x, y| {
@@ -101,7 +101,7 @@
    = note: number of external vids: 4
    = note: where T: '_#2r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1
    |
 LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
@@ -128,7 +128,7 @@
    |
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0:19 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(DefId(0:20 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::'a[0]), 'a))`...
 
-note: External requirements
+note: external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
    |
 LL |       with_signature(a, b, |x, y| {
@@ -145,7 +145,7 @@
    = note: number of external vids: 4
    = note: where T: '_#3r
 
-note: No external requirements
+note: no external requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
    |
 LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
diff --git a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
index a68c3cf..6547ae3 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Zborrowck=mir -Zverbose
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // Test that we assume that universal types like `T` outlive the
 // function body.
diff --git a/src/test/ui/nll/user-annotations/downcast-infer.rs b/src/test/ui/nll/user-annotations/downcast-infer.rs
index 3efea71..b27429f 100644
--- a/src/test/ui/nll/user-annotations/downcast-infer.rs
+++ b/src/test/ui/nll/user-annotations/downcast-infer.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // Check that we don't try to downcast `_` when type-checking the annotation.
 fn main() {
diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr
index 8cb690a..65946ee 100644
--- a/src/test/ui/no-send-res-ports.stderr
+++ b/src/test/ui/no-send-res-ports.stderr
@@ -1,13 +1,20 @@
 error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
   --> $DIR/no-send-res-ports.rs:29:5
    |
-LL |     thread::spawn(move|| {
-   |     ^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
+LL |       thread::spawn(move|| {
+   |  _____^^^^^^^^^^^^^_-
+   | |     |
+   | |     `std::rc::Rc<()>` cannot be sent between threads safely
+LL | |
+LL | |         let y = x;
+LL | |         println!("{:?}", y);
+LL | |     });
+   | |_____- within this `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]`
    | 
   ::: $SRC_DIR/libstd/thread/mod.rs:LL:COL
    |
-LL |     F: Send + 'static,
-   |        ---- required by this bound in `std::thread::spawn`
+LL |       F: Send + 'static,
+   |          ---- required by this bound in `std::thread::spawn`
    |
    = help: within `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
    = note: required because it appears within the type `Port<()>`
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
index b05c29c..074ed66 100644
--- a/src/test/ui/non-copyable-void.stderr
+++ b/src/test/ui/non-copyable-void.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `libc::c_void` in the current scope
+error[E0599]: no method named `clone` found for enum `libc::c_void` in the current scope
   --> $DIR/non-copyable-void.rs:11:23
    |
 LL |         let _z = (*y).clone();
diff --git a/src/test/ui/non-ice-error-on-worker-io-fail.rs b/src/test/ui/non-ice-error-on-worker-io-fail.rs
new file mode 100644
index 0000000..8af1774
--- /dev/null
+++ b/src/test/ui/non-ice-error-on-worker-io-fail.rs
@@ -0,0 +1,37 @@
+// Issue #66530: We would ICE if someone compiled with `-o /dev/null`,
+// because we would try to generate auxiliary files in `/dev/` (which
+// at least the OS X file system rejects).
+//
+// An attempt to `-o` into a directory we cannot write into should indeed
+// be an error; but not an ICE.
+
+// compile-flags: -o /dev/null
+
+// The error-pattern check occurs *before* normalization, and the error patterns
+// are wildly different between build environments. So this is a cop-out (and we
+// rely on the checking of the normalized stderr output as our actual
+// "verification" of the diagnostic).
+
+// error-pattern: error
+
+// On Mac OS X, we get an error like the below
+// normalize-stderr-test "failed to write bytecode to /dev/null.non_ice_error_on_worker_io_fail.*" -> "io error modifying /dev/"
+
+// On Linux, we get an error like the below
+// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /dev/"
+
+// ignore-tidy-linelength
+// ignore-windows - this is a unix-specific test
+// ignore-emscripten - the file-system issues do not replicate here
+// ignore-wasm - the file-system issues do not replicate here
+// ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu
+
+#![crate_type="lib"]
+
+#![cfg_attr(not(feature = "std"), no_std)]
+pub mod task {
+    pub mod __internal {
+        use crate::task::Waker;
+    }
+    pub use core::task::Waker;
+}
diff --git a/src/test/ui/non-ice-error-on-worker-io-fail.stderr b/src/test/ui/non-ice-error-on-worker-io-fail.stderr
new file mode 100644
index 0000000..f5601ad
--- /dev/null
+++ b/src/test/ui/non-ice-error-on-worker-io-fail.stderr
@@ -0,0 +1,6 @@
+warning: ignoring --out-dir flag due to -o flag
+
+error: io error modifying /dev/
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index c1c5021..6c3c4a6 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `Foo` in the current scope
+error[E0599]: no method named `clone` found for struct `Foo` in the current scope
   --> $DIR/noncopyable-class.rs:34:16
    |
 LL | struct Foo {
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
index b66391b..20c7f81 100644
--- a/src/test/ui/not-clone-closure.stderr
+++ b/src/test/ui/not-clone-closure.stderr
@@ -1,8 +1,14 @@
 error[E0277]: the trait bound `S: std::clone::Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
   --> $DIR/not-clone-closure.rs:11:23
    |
-LL |     let hello = hello.clone();
-   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
+LL |       let hello = move || {
+   |  _________________-
+LL | |         println!("Hello {}", a.0);
+LL | |     };
+   | |_____- within this `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
+LL | 
+LL |       let hello = hello.clone();
+   |                         ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
    |
    = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
 
diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr
index 2df628e..855894b 100644
--- a/src/test/ui/object-pointer-types.stderr
+++ b/src/test/ui/object-pointer-types.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `owned` found for type `&dyn Foo` in the current scope
+error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:11:7
    |
 LL |     x.owned();
@@ -8,7 +8,7 @@
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error[E0599]: no method named `owned` found for type `&mut dyn Foo` in the current scope
+error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:17:7
    |
 LL |     x.owned();
@@ -18,7 +18,7 @@
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error[E0599]: no method named `managed` found for type `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
+error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
   --> $DIR/object-pointer-types.rs:23:7
    |
 LL |     x.managed();
diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
index d7c191b..8b0be2e 100644
--- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
diff --git a/src/test/ui/or-patterns/exhaustiveness-pass.rs b/src/test/ui/or-patterns/exhaustiveness-pass.rs
index ce0fe6f..f0dc344 100644
--- a/src/test/ui/or-patterns/exhaustiveness-pass.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-pass.rs
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
index 860c7a1..81bc117 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
diff --git a/src/test/ui/order-dependent-cast-inference.stderr b/src/test/ui/order-dependent-cast-inference.stderr
index 081038c..ad50b41 100644
--- a/src/test/ui/order-dependent-cast-inference.stderr
+++ b/src/test/ui/order-dependent-cast-inference.stderr
@@ -6,7 +6,7 @@
    |                      |
    |                      help: consider giving more type information
    |
-   = note: The type information given here is insufficient to check whether the pointer cast is valid
+   = note: the type information given here is insufficient to check whether the pointer cast is valid
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs
index caa130e..bd99af9 100644
--- a/src/test/ui/panic-handler/panic-handler-duplicate.rs
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.rs
@@ -12,6 +12,6 @@
 }
 
 #[lang = "panic_impl"]
-fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
+fn panic2(info: &PanicInfo) -> ! { //~ ERROR found duplicate lang item `panic_impl`
     loop {}
 }
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.stderr b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
index e9b1945..9999e32 100644
--- a/src/test/ui/panic-handler/panic-handler-duplicate.stderr
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
@@ -1,4 +1,4 @@
-error[E0152]: duplicate lang item found: `panic_impl`.
+error[E0152]: found duplicate lang item `panic_impl`
   --> $DIR/panic-handler-duplicate.rs:15:1
    |
 LL | / fn panic2(info: &PanicInfo) -> ! {
@@ -6,7 +6,7 @@
 LL | | }
    | |_^
    |
-note: first defined here.
+note: first defined here
   --> $DIR/panic-handler-duplicate.rs:10:1
    |
 LL | / fn panic(info: &PanicInfo) -> ! {
diff --git a/src/test/ui/panic-handler/panic-handler-std.rs b/src/test/ui/panic-handler/panic-handler-std.rs
index fffb597..0acc272 100644
--- a/src/test/ui/panic-handler/panic-handler-std.rs
+++ b/src/test/ui/panic-handler/panic-handler-std.rs
@@ -1,4 +1,4 @@
-// error-pattern: duplicate lang item found: `panic_impl`.
+// error-pattern: found duplicate lang item `panic_impl`
 
 
 use std::panic::PanicInfo;
diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr
index e6d2434..ac56513 100644
--- a/src/test/ui/panic-handler/panic-handler-std.stderr
+++ b/src/test/ui/panic-handler/panic-handler-std.stderr
@@ -1,4 +1,4 @@
-error[E0152]: duplicate lang item found: `panic_impl`.
+error[E0152]: found duplicate lang item `panic_impl`
   --> $DIR/panic-handler-std.rs:7:1
    |
 LL | / fn panic(info: PanicInfo) -> ! {
@@ -6,7 +6,7 @@
 LL | | }
    | |_^
    |
-   = note: first defined in crate `std` (which `panic_handler_std` depends on).
+   = note: first defined in crate `std` (which `panic_handler_std` depends on)
 
 error: argument should be `&PanicInfo`
   --> $DIR/panic-handler-std.rs:7:16
diff --git a/src/test/ui/parse-error-correct.rs b/src/test/ui/parse-error-correct.rs
index f167b35..13759a2 100644
--- a/src/test/ui/parse-error-correct.rs
+++ b/src/test/ui/parse-error-correct.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test that the parser is error correcting missing idents. Despite a parsing
 // error (or two), we still run type checking (and don't get extra errors there).
 
diff --git a/src/test/ui/parse-error-correct.stderr b/src/test/ui/parse-error-correct.stderr
index d593431..c54baf0 100644
--- a/src/test/ui/parse-error-correct.stderr
+++ b/src/test/ui/parse-error-correct.stderr
@@ -1,17 +1,17 @@
 error: unexpected token: `;`
-  --> $DIR/parse-error-correct.rs:8:15
+  --> $DIR/parse-error-correct.rs:6:15
    |
 LL |     let x = y.;
    |               ^
 
 error: unexpected token: `(`
-  --> $DIR/parse-error-correct.rs:9:15
+  --> $DIR/parse-error-correct.rs:7:15
    |
 LL |     let x = y.();
    |               ^
 
 error[E0618]: expected function, found `{integer}`
-  --> $DIR/parse-error-correct.rs:9:13
+  --> $DIR/parse-error-correct.rs:7:13
    |
 LL |     let y = 42;
    |         - `{integer}` defined here
@@ -22,7 +22,7 @@
    |             call expression requires function
 
 error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
-  --> $DIR/parse-error-correct.rs:11:15
+  --> $DIR/parse-error-correct.rs:9:15
    |
 LL |     let x = y.foo;
    |               ^^^
diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs
index dcc0dc0..7e26b4f 100644
--- a/src/test/ui/parser-recovery-1.rs
+++ b/src/test/ui/parser-recovery-1.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test that we can recover from missing braces in the parser.
 
 trait Foo {
diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr
index 4d88191..f56060c 100644
--- a/src/test/ui/parser-recovery-1.stderr
+++ b/src/test/ui/parser-recovery-1.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/parser-recovery-1.rs:15:54
+  --> $DIR/parser-recovery-1.rs:13:54
    |
 LL | trait Foo {
    |           - unclosed delimiter
@@ -13,19 +13,19 @@
    |                                                      ^
 
 error: unexpected token: `;`
-  --> $DIR/parser-recovery-1.rs:12:15
+  --> $DIR/parser-recovery-1.rs:10: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:5: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:10:13
    |
 LL |     let x = y.;
    |             ^ not found in this scope
diff --git a/src/test/ui/parser-recovery-2.rs b/src/test/ui/parser-recovery-2.rs
index dc5be96..48b22af 100644
--- a/src/test/ui/parser-recovery-2.rs
+++ b/src/test/ui/parser-recovery-2.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test that we can recover from mismatched braces in the parser.
 
 trait Foo {
diff --git a/src/test/ui/parser-recovery-2.stderr b/src/test/ui/parser-recovery-2.stderr
index c48211d..cd3da4c 100644
--- a/src/test/ui/parser-recovery-2.stderr
+++ b/src/test/ui/parser-recovery-2.stderr
@@ -1,11 +1,11 @@
 error: unexpected token: `;`
-  --> $DIR/parser-recovery-2.rs:12:15
+  --> $DIR/parser-recovery-2.rs:10:15
    |
 LL |     let x = y.;
    |               ^
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/parser-recovery-2.rs:8:5
+  --> $DIR/parser-recovery-2.rs:6:5
    |
 LL |     fn bar() {
    |              - unclosed delimiter
@@ -14,13 +14,13 @@
    |     ^ mismatched closing delimiter
 
 error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/parser-recovery-2.rs:7:17
+  --> $DIR/parser-recovery-2.rs:5:17
    |
 LL |         let x = foo();
    |                 ^^^ not found in this scope
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/parser-recovery-2.rs:12:13
+  --> $DIR/parser-recovery-2.rs:10:13
    |
 LL |     let x = y.;
    |             ^ not found in this scope
diff --git a/src/test/ui/parser/ascii-only-character-escape.rs b/src/test/ui/parser/ascii-only-character-escape.rs
index f1b028e..20d3edf 100644
--- a/src/test/ui/parser/ascii-only-character-escape.rs
+++ b/src/test/ui/parser/ascii-only-character-escape.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     let x = "\x80"; //~ ERROR may only be used
     let y = "\xff"; //~ ERROR may only be used
diff --git a/src/test/ui/parser/ascii-only-character-escape.stderr b/src/test/ui/parser/ascii-only-character-escape.stderr
index 3916779..cf51b00 100644
--- a/src/test/ui/parser/ascii-only-character-escape.stderr
+++ b/src/test/ui/parser/ascii-only-character-escape.stderr
@@ -1,17 +1,17 @@
 error: this form of character escape may only be used with characters in the range [\x00-\x7f]
-  --> $DIR/ascii-only-character-escape.rs:4:14
+  --> $DIR/ascii-only-character-escape.rs:2:14
    |
 LL |     let x = "\x80";
    |              ^^^^
 
 error: this form of character escape may only be used with characters in the range [\x00-\x7f]
-  --> $DIR/ascii-only-character-escape.rs:5:14
+  --> $DIR/ascii-only-character-escape.rs:3:14
    |
 LL |     let y = "\xff";
    |              ^^^^
 
 error: this form of character escape may only be used with characters in the range [\x00-\x7f]
-  --> $DIR/ascii-only-character-escape.rs:6:14
+  --> $DIR/ascii-only-character-escape.rs:4:14
    |
 LL |     let z = "\xe2";
    |              ^^^^
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
index f6d2bee..118bff8 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -1,3 +1,5 @@
+#![feature(half_open_range_patterns)]
+
 fn main() {}
 
 #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
@@ -90,15 +92,15 @@
 // note: requires parens in patterns to allow disambiguation
 
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
 //~^ ERROR unexpected token: `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-//~^ ERROR `X..=` range patterns are not supported
+//~^ ERROR inclusive range with no end
 //~| ERROR expected one of `=>`, `if`, or `|`, found `#`
 
 #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
index 0123006..4775b9b 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -1,5 +1,5 @@
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:3:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:5:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
    |                                    ^^^^^^^^
@@ -7,19 +7,19 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `]`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:5:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:7:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
    |                                        ^ expected expression
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:7:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
    |                                   ^ expected one of 7 possible tokens
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:9:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:11:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                    ^^^^^^^^
@@ -27,13 +27,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `)`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:9:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:11:44
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                            ^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:12:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:14:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                      ^^^^^^^^
@@ -41,13 +41,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `)`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:12:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:14:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                              ^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:15:36
+  --> $DIR/attr-stmt-expr-attr-bad.rs:17:36
    |
 LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
    |                                    ^^^^^^^^
@@ -55,7 +55,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:17:33
+  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
    |
 LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
    |                                 ^^^^^^^^
@@ -63,7 +63,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
+  --> $DIR/attr-stmt-expr-attr-bad.rs:21:33
    |
 LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
    |                                 ^^^^^^^^
@@ -71,13 +71,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:21:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:23:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
    |                                  ^ expected one of 7 possible tokens
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:23:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:25:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
    |                                   ^^^^^^^^
@@ -85,7 +85,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:25:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:27:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
    |                                        ^^^^^^^^
@@ -93,7 +93,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:27:35
+  --> $DIR/attr-stmt-expr-attr-bad.rs:29:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
    |                                   ^^^^^^^^
@@ -101,7 +101,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:29:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    |                                        ^^^^^^^^
@@ -109,19 +109,19 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected expression, found `..`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
    |                                        ^^ expected expression
 
 error: expected expression, found `..`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:35:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
    |                                        ^^ expected expression
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:35:41
+  --> $DIR/attr-stmt-expr-attr-bad.rs:37:41
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
    |                                         ^^^^^^^^
@@ -129,7 +129,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:37:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:39:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |                                             ^^^^^^^^
@@ -137,13 +137,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:39:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:41:32
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
    |                                ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
+  --> $DIR/attr-stmt-expr-attr-bad.rs:43:37
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
    |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -152,7 +152,7 @@
    |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:45:38
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    |                                      ^^^^^^^^
@@ -160,13 +160,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
+  --> $DIR/attr-stmt-expr-attr-bad.rs:47:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
    |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:49:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
    |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -174,7 +174,7 @@
    |                                             expected `{`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |                                              ^^^^^^^^
@@ -182,13 +182,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:53:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
    |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
@@ -196,7 +196,7 @@
    |                                             expected `{`
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:54:50
+  --> $DIR/attr-stmt-expr-attr-bad.rs:56:50
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
    |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -205,7 +205,7 @@
    |                                             this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:56:51
+  --> $DIR/attr-stmt-expr-attr-bad.rs:58:51
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |                                                   ^^^^^^^^
@@ -213,13 +213,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:58:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:60:32
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
    |                                ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:60:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:62:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
    |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -228,7 +228,7 @@
    |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:62:46
+  --> $DIR/attr-stmt-expr-attr-bad.rs:64:46
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    |                                              ^^^^^^^^
@@ -236,13 +236,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:64:48
+  --> $DIR/attr-stmt-expr-attr-bad.rs:66:48
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
    |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:66:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:68:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
    |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -250,7 +250,7 @@
    |                                                     expected `{`
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:68:54
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:54
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |                                                      ^^^^^^^^
@@ -258,13 +258,13 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: attributes are not yet allowed on `if` expressions
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
    |                                                     ^^^^^^^
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+  --> $DIR/attr-stmt-expr-attr-bad.rs:72:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
    |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
@@ -272,7 +272,7 @@
    |                                                     expected `{`
 
 error: expected `{`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:73:66
+  --> $DIR/attr-stmt-expr-attr-bad.rs:75:66
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
    |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
@@ -281,7 +281,7 @@
    |                                                     this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr-stmt-expr-attr-bad.rs:75:67
+  --> $DIR/attr-stmt-expr-attr-bad.rs:77:67
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
    |                                                                   ^^^^^^^^
@@ -289,7 +289,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -299,7 +299,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -309,7 +309,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -319,7 +319,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -329,7 +329,7 @@
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
+  --> $DIR/attr-stmt-expr-attr-bad.rs:88:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
    |                        ------- ^^^^^^^^ not permitted following an outer attibute
@@ -338,83 +338,90 @@
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:92:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:92:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:94:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:95:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:97:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:95:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:97:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:98:39
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:39
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
    |                                       ^
 
-error: `X..=` range patterns are not supported
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+error[E0586]: inclusive range with no end
+  --> $DIR/attr-stmt-expr-attr-bad.rs:102:35
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                                   ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: expected one of `=>`, `if`, or `|`, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:100:38
+  --> $DIR/attr-stmt-expr-attr-bad.rs:102:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    |                                      ^ expected one of `=>`, `if`, or `|`
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:104:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:104:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:106:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: unexpected token: `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:107:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^
 
 error: expected one of `.`, `;`, `?`, or an operator, found `#`
-  --> $DIR/attr-stmt-expr-attr-bad.rs:107:34
+  --> $DIR/attr-stmt-expr-attr-bad.rs:109:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^ expected one of `.`, `;`, `?`, or an operator
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:112:44
+  --> $DIR/attr-stmt-expr-attr-bad.rs:114:44
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
    |                                            ^
 
 error: expected statement after outer attribute
-  --> $DIR/attr-stmt-expr-attr-bad.rs:114:45
+  --> $DIR/attr-stmt-expr-attr-bad.rs:116:45
    |
 LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
    |                                             ^
 
 error: aborting due to 57 previous errors
 
+For more information about this error, try `rustc --explain E0586`.
diff --git a/src/test/ui/parser/bad-char-literals.rs b/src/test/ui/parser/bad-char-literals.rs
index 1c9b597..11696b8 100644
--- a/src/test/ui/parser/bad-char-literals.rs
+++ b/src/test/ui/parser/bad-char-literals.rs
Binary files differ
diff --git a/src/test/ui/parser/bad-char-literals.stderr b/src/test/ui/parser/bad-char-literals.stderr
index 8e96ea2..093978f 100644
--- a/src/test/ui/parser/bad-char-literals.stderr
+++ b/src/test/ui/parser/bad-char-literals.stderr
Binary files differ
diff --git a/src/test/ui/parser/bounds-type.rs b/src/test/ui/parser/bounds-type.rs
index 9122cb4..7a187a0 100644
--- a/src/test/ui/parser/bounds-type.rs
+++ b/src/test/ui/parser/bounds-type.rs
@@ -8,6 +8,11 @@
     T: ?for<'a> Trait, // OK
     T: Tr +, // OK
     T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
+
+    T: ?const Tr, // OK
+    T: ?const ?Tr, // OK
+    T: ?const Tr + 'a, // OK
+    T: ?const 'a, //~ ERROR `?const` may only modify trait bounds, not lifetime bounds
 >;
 
 fn main() {}
diff --git a/src/test/ui/parser/bounds-type.stderr b/src/test/ui/parser/bounds-type.stderr
index 0b714e4..9a1f2ed 100644
--- a/src/test/ui/parser/bounds-type.stderr
+++ b/src/test/ui/parser/bounds-type.stderr
@@ -4,5 +4,11 @@
 LL |     T: ?'a,
    |        ^
 
-error: aborting due to previous error
+error: `?const` may only modify trait bounds, not lifetime bounds
+  --> $DIR/bounds-type.rs:15:8
+   |
+LL |     T: ?const 'a,
+   |        ^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs
index bd358af..dadf397 100644
--- a/src/test/ui/parser/byte-literals.rs
+++ b/src/test/ui/parser/byte-literals.rs
@@ -1,6 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
-
 // ignore-tidy-tab
 
 static FOO: u8 = b'\f';  //~ ERROR unknown byte escape
diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr
index 58a5797..53d50af 100644
--- a/src/test/ui/parser/byte-literals.stderr
+++ b/src/test/ui/parser/byte-literals.stderr
@@ -1,41 +1,41 @@
 error: unknown byte escape: f
-  --> $DIR/byte-literals.rs:6:21
+  --> $DIR/byte-literals.rs:3:21
    |
 LL | static FOO: u8 = b'\f';
    |                     ^ unknown byte escape
 
 error: unknown byte escape: f
-  --> $DIR/byte-literals.rs:9:8
+  --> $DIR/byte-literals.rs:6:8
    |
 LL |     b'\f';
    |        ^ unknown byte escape
 
 error: invalid character in numeric character escape: Z
-  --> $DIR/byte-literals.rs:10:10
+  --> $DIR/byte-literals.rs:7:10
    |
 LL |     b'\x0Z';
    |          ^
 
 error: byte constant must be escaped: \t
-  --> $DIR/byte-literals.rs:11:7
+  --> $DIR/byte-literals.rs:8:7
    |
 LL |     b'    ';
    |       ^^^^
 
 error: byte constant must be escaped: '
-  --> $DIR/byte-literals.rs:12:7
+  --> $DIR/byte-literals.rs:9:7
    |
 LL |     b''';
    |       ^
 
 error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
-  --> $DIR/byte-literals.rs:13:7
+  --> $DIR/byte-literals.rs:10:7
    |
 LL |     b'é';
    |       ^
 
 error: unterminated byte constant
-  --> $DIR/byte-literals.rs:14:6
+  --> $DIR/byte-literals.rs:11:6
    |
 LL |     b'a
    |      ^^^^
diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs
index 8d8ee4d..caffd9e 100644
--- a/src/test/ui/parser/byte-string-literals.rs
+++ b/src/test/ui/parser/byte-string-literals.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 static FOO: &'static [u8] = b"\f";  //~ ERROR unknown byte escape
 
 pub fn main() {
diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr
index eeb2fcd..ca964cd 100644
--- a/src/test/ui/parser/byte-string-literals.stderr
+++ b/src/test/ui/parser/byte-string-literals.stderr
@@ -1,29 +1,29 @@
 error: unknown byte escape: f
-  --> $DIR/byte-string-literals.rs:3:32
+  --> $DIR/byte-string-literals.rs:1:32
    |
 LL | static FOO: &'static [u8] = b"\f";
    |                                ^ unknown byte escape
 
 error: unknown byte escape: f
-  --> $DIR/byte-string-literals.rs:6:8
+  --> $DIR/byte-string-literals.rs:4:8
    |
 LL |     b"\f";
    |        ^ unknown byte escape
 
 error: invalid character in numeric character escape: Z
-  --> $DIR/byte-string-literals.rs:7:10
+  --> $DIR/byte-string-literals.rs:5:10
    |
 LL |     b"\x0Z";
    |          ^
 
 error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
-  --> $DIR/byte-string-literals.rs:8:7
+  --> $DIR/byte-string-literals.rs:6:7
    |
 LL |     b"é";
    |       ^
 
 error: unterminated double quote byte string
-  --> $DIR/byte-string-literals.rs:9:6
+  --> $DIR/byte-string-literals.rs:7:6
    |
 LL |       b"a
    |  ______^
diff --git a/src/test/ui/parser/chained-comparison-suggestion.rs b/src/test/ui/parser/chained-comparison-suggestion.rs
new file mode 100644
index 0000000..0431196
--- /dev/null
+++ b/src/test/ui/parser/chained-comparison-suggestion.rs
@@ -0,0 +1,40 @@
+// Check that we get nice suggestions when attempting a chained comparison.
+
+fn comp1() {
+    1 < 2 <= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp2() {
+    1 < 2 < 3; //~ ERROR comparison operators cannot be chained
+}
+
+fn comp3() {
+    1 <= 2 < 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp4() {
+    1 <= 2 <= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp5() {
+    1 > 2 >= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn comp6() {
+    1 > 2 > 3; //~ ERROR comparison operators cannot be chained
+}
+
+fn comp7() {
+    1 >= 2 > 3; //~ ERROR comparison operators cannot be chained
+}
+
+fn comp8() {
+    1 >= 2 >= 3; //~ ERROR comparison operators cannot be chained
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/chained-comparison-suggestion.stderr b/src/test/ui/parser/chained-comparison-suggestion.stderr
new file mode 100644
index 0000000..5c10a45
--- /dev/null
+++ b/src/test/ui/parser/chained-comparison-suggestion.stderr
@@ -0,0 +1,159 @@
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:4:7
+   |
+LL |     1 < 2 <= 3;
+   |       ^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 < 2 && 2 <= 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 < 2) <= 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:9:7
+   |
+LL |     1 < 2 < 3;
+   |       ^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+help: split the comparison into two...
+   |
+LL |     1 < 2 && 2 < 3;
+   |     ^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 < 2) < 3;
+   |     ^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:13:7
+   |
+LL |     1 <= 2 < 3;
+   |       ^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 <= 2 && 2 < 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 <= 2) < 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:18:7
+   |
+LL |     1 <= 2 <= 3;
+   |       ^^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 <= 2 && 2 <= 3;
+   |     ^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 <= 2) <= 3;
+   |     ^^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:23:7
+   |
+LL |     1 > 2 >= 3;
+   |       ^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 > 2 && 2 >= 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 > 2) >= 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:28:7
+   |
+LL |     1 > 2 > 3;
+   |       ^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+help: split the comparison into two...
+   |
+LL |     1 > 2 && 2 > 3;
+   |     ^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 > 2) > 3;
+   |     ^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:32:7
+   |
+LL |     1 >= 2 > 3;
+   |       ^^^^^^
+   |
+   = help: use `::<...>` instead of `<...>` to specify type arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+help: split the comparison into two...
+   |
+LL |     1 >= 2 && 2 > 3;
+   |     ^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 >= 2) > 3;
+   |     ^^^^^^^^^^
+
+error: comparison operators cannot be chained
+  --> $DIR/chained-comparison-suggestion.rs:36:7
+   |
+LL |     1 >= 2 >= 3;
+   |       ^^^^^^^
+   |
+help: split the comparison into two...
+   |
+LL |     1 >= 2 && 2 >= 3;
+   |     ^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (1 >= 2) >= 3;
+   |     ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:4:14
+   |
+LL |     1 < 2 <= 3;
+   |              ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:13:14
+   |
+LL |     1 <= 2 < 3;
+   |              ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:18:15
+   |
+LL |     1 <= 2 <= 3;
+   |               ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:23:14
+   |
+LL |     1 > 2 >= 3;
+   |              ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/chained-comparison-suggestion.rs:36:15
+   |
+LL |     1 >= 2 >= 3;
+   |               ^ expected `bool`, found integer
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs
index c2a80e8..270c8b4 100644
--- a/src/test/ui/parser/impl-parsing.rs
+++ b/src/test/ui/parser/impl-parsing.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 impl ! {} // OK
 impl ! where u8: Copy {} // OK
 
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
index e929fa5..7c2a793 100644
--- a/src/test/ui/parser/impl-parsing.stderr
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -1,29 +1,29 @@
 error: missing `for` in a trait impl
-  --> $DIR/impl-parsing.rs:6:11
+  --> $DIR/impl-parsing.rs:4:11
    |
 LL | impl Trait Type {}
    |           ^ help: add `for` here
 
 error: missing `for` in a trait impl
-  --> $DIR/impl-parsing.rs:7:11
+  --> $DIR/impl-parsing.rs:5:11
    |
 LL | impl Trait .. {}
    |           ^ help: add `for` here
 
 error: expected a trait, found type
-  --> $DIR/impl-parsing.rs:8:6
+  --> $DIR/impl-parsing.rs:6:6
    |
 LL | impl ?Sized for Type {}
    |      ^^^^^^
 
 error: expected a trait, found type
-  --> $DIR/impl-parsing.rs:9:6
+  --> $DIR/impl-parsing.rs:7:6
    |
 LL | impl ?Sized for .. {}
    |      ^^^^^^
 
 error: expected `impl`, found `FAIL`
-  --> $DIR/impl-parsing.rs:11:16
+  --> $DIR/impl-parsing.rs:9:16
    |
 LL | default unsafe FAIL
    |                ^^^^ expected `impl`
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs
index 5362997..ab445a9 100644
--- a/src/test/ui/parser/issue-23620-invalid-escapes.rs
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     let _ = b"\u{a66e}";
     //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
index 5fabc1d..b391ac7 100644
--- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
@@ -1,17 +1,17 @@
 error: unicode escape sequences cannot be used as a byte or in a byte string
-  --> $DIR/issue-23620-invalid-escapes.rs:4:15
+  --> $DIR/issue-23620-invalid-escapes.rs:2:15
    |
 LL |     let _ = b"\u{a66e}";
    |               ^^^^^^^^
 
 error: unicode escape sequences cannot be used as a byte or in a byte string
-  --> $DIR/issue-23620-invalid-escapes.rs:7:15
+  --> $DIR/issue-23620-invalid-escapes.rs:5:15
    |
 LL |     let _ = b'\u{a66e}';
    |               ^^^^^^^^
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:10:15
+  --> $DIR/issue-23620-invalid-escapes.rs:8:15
    |
 LL |     let _ = b'\u';
    |               ^^ incorrect unicode escape sequence
@@ -19,43 +19,43 @@
    = help: format of unicode escape sequences is `\u{...}`
 
 error: numeric character escape is too short
-  --> $DIR/issue-23620-invalid-escapes.rs:13:15
+  --> $DIR/issue-23620-invalid-escapes.rs:11:15
    |
 LL |     let _ = b'\x5';
    |               ^^^
 
 error: invalid character in numeric character escape: x
-  --> $DIR/issue-23620-invalid-escapes.rs:16:17
+  --> $DIR/issue-23620-invalid-escapes.rs:14:17
    |
 LL |     let _ = b'\xxy';
    |                 ^
 
 error: numeric character escape is too short
-  --> $DIR/issue-23620-invalid-escapes.rs:19:14
+  --> $DIR/issue-23620-invalid-escapes.rs:17:14
    |
 LL |     let _ = '\x5';
    |              ^^^
 
 error: invalid character in numeric character escape: x
-  --> $DIR/issue-23620-invalid-escapes.rs:22:16
+  --> $DIR/issue-23620-invalid-escapes.rs:20:16
    |
 LL |     let _ = '\xxy';
    |                ^
 
 error: unicode escape sequences cannot be used as a byte or in a byte string
-  --> $DIR/issue-23620-invalid-escapes.rs:25:15
+  --> $DIR/issue-23620-invalid-escapes.rs:23:15
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
    |               ^^^^^^^^
 
 error: invalid character in numeric character escape:  
-  --> $DIR/issue-23620-invalid-escapes.rs:25:27
+  --> $DIR/issue-23620-invalid-escapes.rs:23:27
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
    |                           ^
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:25:28
+  --> $DIR/issue-23620-invalid-escapes.rs:23:28
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
    |                            ^^ incorrect unicode escape sequence
@@ -63,13 +63,13 @@
    = help: format of unicode escape sequences is `\u{...}`
 
 error: invalid character in numeric character escape:  
-  --> $DIR/issue-23620-invalid-escapes.rs:30:17
+  --> $DIR/issue-23620-invalid-escapes.rs:28:17
    |
 LL |     let _ = "\xf \u";
    |                 ^
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:30:18
+  --> $DIR/issue-23620-invalid-escapes.rs:28:18
    |
 LL |     let _ = "\xf \u";
    |                  ^^ incorrect unicode escape sequence
@@ -77,7 +77,7 @@
    = help: format of unicode escape sequences is `\u{...}`
 
 error: incorrect unicode escape sequence
-  --> $DIR/issue-23620-invalid-escapes.rs:34:14
+  --> $DIR/issue-23620-invalid-escapes.rs:32:14
    |
 LL |     let _ = "\u8f";
    |              ^^--
diff --git a/src/test/ui/parser/issue-62913.rs b/src/test/ui/parser/issue-62913.rs
index cfa19a2..0db06f6 100644
--- a/src/test/ui/parser/issue-62913.rs
+++ b/src/test/ui/parser/issue-62913.rs
@@ -1,3 +1,4 @@
 "\u\\"
 //~^ ERROR incorrect unicode escape sequence
 //~| ERROR invalid trailing slash in literal
+//~| ERROR expected item, found `"\u\\"`
diff --git a/src/test/ui/parser/issue-62913.stderr b/src/test/ui/parser/issue-62913.stderr
index 05c5c4d..f72174f 100644
--- a/src/test/ui/parser/issue-62913.stderr
+++ b/src/test/ui/parser/issue-62913.stderr
@@ -12,5 +12,11 @@
 LL | "\u\"
    |     ^
 
-error: aborting due to 2 previous errors
+error: expected item, found `"\u\"`
+  --> $DIR/issue-62913.rs:1:1
+   |
+LL | "\u\"
+   | ^^^^^^ expected item
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/issue-62973.rs b/src/test/ui/parser/issue-62973.rs
index 18bc51e..1c5d0c6 100644
--- a/src/test/ui/parser/issue-62973.rs
+++ b/src/test/ui/parser/issue-62973.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 6 previous errors
+// error-pattern: aborting due to 7 previous errors
 
 fn main() {}
 
diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issue-62973.stderr
index e95e629..95ee52d 100644
--- a/src/test/ui/parser/issue-62973.stderr
+++ b/src/test/ui/parser/issue-62973.stderr
@@ -9,6 +9,17 @@
 LL | 
    |  ^
 
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62973.rs:8:2
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |        -         - unclosed delimiter
+   |        |
+   |        unclosed delimiter
+LL | 
+LL | 
+   |  ^
+
 error: expected one of `,` or `}`, found `{`
   --> $DIR/issue-62973.rs:6:25
    |
@@ -60,5 +71,5 @@
    |                              |
    |                              unclosed delimiter
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
index a7d10ca..8efb3c7 100644
--- a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
+++ b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs
@@ -1,6 +1,7 @@
 // check-pass
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 
 #![allow(ellipsis_inclusive_range_patterns)]
 
@@ -10,6 +11,11 @@
             if let 2...$e = 3 {}
             if let 2..=$e = 3 {}
             if let 2..$e = 3 {}
+            if let ..$e = 3 {}
+            if let ..=$e = 3 {}
+            if let $e.. = 5 {}
+            if let $e..5 = 4 {}
+            if let $e..=5 = 4 {}
         }
     }
     mac_expr!(4);
diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs
index a5a8de8..d5f5f14 100644
--- a/src/test/ui/parser/issue-63135.rs
+++ b/src/test/ui/parser/issue-63135.rs
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 5 previous errors
+// error-pattern: aborting due to 6 previous errors
 
 fn i(n{...,f #
diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr
index a6fb037..462fdf1 100644
--- a/src/test/ui/parser/issue-63135.stderr
+++ b/src/test/ui/parser/issue-63135.stderr
@@ -7,6 +7,15 @@
    |     | unclosed delimiter
    |     unclosed delimiter
 
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-63135.rs:3:16
+   |
+LL | fn i(n{...,f #
+   |     - -        ^
+   |     | |
+   |     | unclosed delimiter
+   |     unclosed delimiter
+
 error: expected field pattern, found `...`
   --> $DIR/issue-63135.rs:3:8
    |
@@ -34,5 +43,5 @@
 LL | fn i(n{...,f #
    |                ^ expected one of `:` or `|`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
index 1730adf..5ec143f 100644
--- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
+++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 // The problem in #66357 was that the call trace:
 //
 // - parse_fn_block_decl
@@ -11,4 +13,4 @@
 
 fn f() { |[](* }
 //~^ ERROR expected one of `,` or `:`, found `(`
-//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
index 00d84e2a..c381099 100644
--- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
+++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
@@ -1,11 +1,11 @@
 error: expected one of `,` or `:`, found `(`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
+  --> $DIR/issue-66357-unexpected-unreachable.rs:14:13
    |
 LL | fn f() { |[](* }
    |             ^ expected one of `,` or `:`
 
-error: expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:14
+error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+  --> $DIR/issue-66357-unexpected-unreachable.rs:14:14
    |
 LL | fn f() { |[](* }
    |             -^ help: `)` may belong here
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.rs b/src/test/ui/parser/lex-bad-char-literals-1.rs
index 54d75ed..e7951cf 100644
--- a/src/test/ui/parser/lex-bad-char-literals-1.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-1.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
 static c3: char =
     '\x1' //~ ERROR: numeric character escape is too short
 ;
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr
index 000d155..fcf4802 100644
--- a/src/test/ui/parser/lex-bad-char-literals-1.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-1.stderr
@@ -1,23 +1,23 @@
 error: numeric character escape is too short
-  --> $DIR/lex-bad-char-literals-1.rs:3:6
+  --> $DIR/lex-bad-char-literals-1.rs:2:6
    |
 LL |     '\x1'
    |      ^^^
 
 error: numeric character escape is too short
-  --> $DIR/lex-bad-char-literals-1.rs:7:6
+  --> $DIR/lex-bad-char-literals-1.rs:6:6
    |
 LL |     "\x1"
    |      ^^^
 
 error: unknown character escape: \u{25cf}
-  --> $DIR/lex-bad-char-literals-1.rs:11:7
+  --> $DIR/lex-bad-char-literals-1.rs:10:7
    |
 LL |     '\●'
    |       ^ unknown character escape
 
 error: unknown character escape: \u{25cf}
-  --> $DIR/lex-bad-char-literals-1.rs:15:7
+  --> $DIR/lex-bad-char-literals-1.rs:14:7
    |
 LL |     "\●"
    |       ^ unknown character escape
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.rs b/src/test/ui/parser/lex-bad-char-literals-7.rs
index 70eafcb..1580157 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-7.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
 fn main() {
     let _: char = '';
     //~^ ERROR: empty character literal
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/parser/lex-bad-char-literals-7.stderr
index e1ba3c3..ee9aa86 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-7.stderr
@@ -1,17 +1,17 @@
 error: empty character literal
-  --> $DIR/lex-bad-char-literals-7.rs:3:20
+  --> $DIR/lex-bad-char-literals-7.rs:2:20
    |
 LL |     let _: char = '';
    |                    ^
 
 error: empty unicode escape (must have at least 1 hex digit)
-  --> $DIR/lex-bad-char-literals-7.rs:5:20
+  --> $DIR/lex-bad-char-literals-7.rs:4:20
    |
 LL |     let _: char = '\u{}';
    |                    ^^^^
 
 error: unterminated character literal
-  --> $DIR/lex-bad-char-literals-7.rs:12:13
+  --> $DIR/lex-bad-char-literals-7.rs:11:13
    |
 LL |     let _ = ' hello // here's a comment
    |             ^^^^^^^^
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
index b588b00..9a9f9c4 100644
--- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
Binary files differ
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
index b0fe4b6..598da6b 100644
--- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
Binary files differ
diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr
index fa25161..ae981ac 100644
--- a/src/test/ui/parser/macro/pub-item-macro.stderr
+++ b/src/test/ui/parser/macro/pub-item-macro.stderr
@@ -13,7 +13,16 @@
   --> $DIR/pub-item-macro.rs:17:23
    |
 LL |     let y: u32 = foo::x;
-   |                       ^
+   |                       ^ this static is private
+   |
+note: the static `x` is defined here
+  --> $DIR/pub-item-macro.rs:4:5
+   |
+LL |     static x: u32 = 0;
+   |     ^^^^^^^^^^^^^^^^^^
+...
+LL |     pub_x!();
+   |     --------- in this macro invocation
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/match-vec-invalid.stderr b/src/test/ui/parser/match-vec-invalid.stderr
deleted file mode 100644
index 58343e8..0000000
--- a/src/test/ui/parser/match-vec-invalid.stderr
+++ /dev/null
@@ -1,42 +0,0 @@
-error[E0416]: identifier `tail` is bound more than once in the same pattern
-  --> $DIR/match-vec-invalid.rs:4:24
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                        ^^^^ used in a pattern more than once
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/match-vec-invalid.rs:4:13
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |             ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/match-vec-invalid.rs:4:24
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                        ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error: `..` can only be used once per slice pattern
-  --> $DIR/match-vec-invalid.rs:4:31
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                    --         ^^ can only be used once per slice pattern
-   |                    |
-   |                    previously used here
-
-error[E0308]: mismatched types
-  --> $DIR/match-vec-invalid.rs:13:30
-   |
-LL | const RECOVERY_WITNESS: () = 0;
-   |                              ^ expected `()`, found integer
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0308, E0416, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/missing_right_paren.rs b/src/test/ui/parser/missing_right_paren.rs
index 4f7c5ee..c35236c 100644
--- a/src/test/ui/parser/missing_right_paren.rs
+++ b/src/test/ui/parser/missing_right_paren.rs
@@ -1,3 +1,3 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 2 previous errors
+// error-pattern: aborting due to 3 previous errors
 fn main((ؼ
\ No newline at end of file
diff --git a/src/test/ui/parser/missing_right_paren.stderr b/src/test/ui/parser/missing_right_paren.stderr
index c98b6bb..d67e7c8 100644
--- a/src/test/ui/parser/missing_right_paren.stderr
+++ b/src/test/ui/parser/missing_right_paren.stderr
@@ -7,11 +7,20 @@
    |        |unclosed delimiter
    |        unclosed delimiter
 
+error: this file contains an unclosed delimiter
+  --> $DIR/missing_right_paren.rs:3:11
+   |
+LL | fn main((ؼ
+   |        -- ^
+   |        ||
+   |        |unclosed delimiter
+   |        unclosed delimiter
+
 error: expected one of `:` or `|`, found `)`
   --> $DIR/missing_right_paren.rs:3:11
    |
 LL | fn main((ؼ
    |           ^ expected one of `:` or `|`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs
index f27caa5..7becffa 100644
--- a/src/test/ui/parser/pat-lt-bracket-6.rs
+++ b/src/test/ui/parser/pat-lt-bracket-6.rs
@@ -4,7 +4,6 @@
 
     let Test(&desc[..]) = x;
     //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[`
-    //~^^ ERROR subslice patterns are unstable
 }
 
 const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr
index fe9603c..035d0db 100644
--- a/src/test/ui/parser/pat-lt-bracket-6.stderr
+++ b/src/test/ui/parser/pat-lt-bracket-6.stderr
@@ -7,22 +7,12 @@
    |                   expected one of `)`, `,`, `@`, or `|`
    |                   help: missing `,`
 
-error[E0658]: subslice patterns are unstable
-  --> $DIR/pat-lt-bracket-6.rs:5:20
-   |
-LL |     let Test(&desc[..]) = x;
-   |                    ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
 error[E0308]: mismatched types
-  --> $DIR/pat-lt-bracket-6.rs:10:30
+  --> $DIR/pat-lt-bracket-6.rs:9:30
    |
 LL | const RECOVERY_WITNESS: () = 0;
    |                              ^ expected `()`, found integer
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0658.
-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/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs
deleted file mode 100644
index 2f03160..0000000
--- a/src/test/ui/parser/pat-tuple-4.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-fn main() {
-    const PAT: u8 = 0;
-
-    match 0 {
-        (.. PAT) => {}
-        //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
-    }
-}
-
-const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr
deleted file mode 100644
index 6c64290..0000000
--- a/src/test/ui/parser/pat-tuple-4.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error: `..X` range patterns are not supported
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
-  --> $DIR/pat-tuple-4.rs:11:30
-   |
-LL | const RECOVERY_WITNESS: () = 0;
-   |                              ^ expected `()`, found integer
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs
deleted file mode 100644
index 5334ef9..0000000
--- a/src/test/ui/parser/pat-tuple-5.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    const PAT: u8 = 0;
-
-    match (0, 1) {
-        (PAT ..) => {}
-        //~^ ERROR `X..` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
-        //~| ERROR mismatched types
-    }
-}
diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr
deleted file mode 100644
index 8ff4f94..0000000
--- a/src/test/ui/parser/pat-tuple-5.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error: `X..` range patterns are not supported
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |         (PAT ..) => {}
-   |          ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
-
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |         (PAT ..) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
-  --> $DIR/pat-tuple-5.rs:5:10
-   |
-LL |     match (0, 1) {
-   |           ------ this expression has type `({integer}, {integer})`
-LL |         (PAT ..) => {}
-   |          ^^^ expected tuple, found `u8`
-   |
-   = note: expected tuple `({integer}, {integer})`
-               found type `u8`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/range_inclusive.rs b/src/test/ui/parser/range_inclusive.rs
index bc61c5b..7c3b906 100644
--- a/src/test/ui/parser/range_inclusive.rs
+++ b/src/test/ui/parser/range_inclusive.rs
@@ -2,5 +2,5 @@
 
 pub fn main() {
     for _ in 1..= {} //~ERROR inclusive range with no end
-                     //~^HELP bounded at the end
+                     //~^HELP use `..` instead
 }
diff --git a/src/test/ui/parser/range_inclusive.stderr b/src/test/ui/parser/range_inclusive.stderr
index 12b7eda..1dd4799 100644
--- a/src/test/ui/parser/range_inclusive.stderr
+++ b/src/test/ui/parser/range_inclusive.stderr
@@ -1,10 +1,10 @@
 error[E0586]: inclusive range with no end
-  --> $DIR/range_inclusive.rs:4:19
+  --> $DIR/range_inclusive.rs:4:15
    |
 LL |     for _ in 1..= {}
-   |                   ^
+   |               ^^^ help: use `..` instead
    |
-   = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/raw-byte-string-literals.rs b/src/test/ui/parser/raw-byte-string-literals.rs
index 534afab..163c8ac 100644
--- a/src/test/ui/parser/raw-byte-string-literals.rs
+++ b/src/test/ui/parser/raw-byte-string-literals.rs
Binary files differ
diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs
index 260e108..e07ea62 100644
--- a/src/test/ui/parser/recover-range-pats.rs
+++ b/src/test/ui/parser/recover-range-pats.rs
@@ -4,6 +4,7 @@
 // 2. Or at least we have parser recovery if they don't.
 
 #![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
 #![deny(ellipsis_inclusive_range_patterns)]
 
 fn main() {}
@@ -55,70 +56,66 @@
 }
 
 fn exclusive_from() {
-    if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported
-    if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported
-    if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let 0.. = 0 {}
+    if let X.. = 0 {}
+    if let true.. = 0 {}
     //~^ ERROR only char and numeric types
-    if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let .0.. = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive_from() {
-    if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
-    if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported
-    if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let 0..= = 0 {} //~ ERROR inclusive range with no end
+    if let X..= = 0 {} //~ ERROR inclusive range with no end
+    if let true..= = 0 {} //~ ERROR inclusive range with no end
     //~| ERROR only char and numeric types
-    if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let .0..= = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive2_from() {
-    if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let X... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let true... = 0 {} //~ ERROR `X...` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
+    if let 0... = 0 {} //~ ERROR inclusive range with no end
+    if let X... = 0 {} //~ ERROR inclusive range with no end
+    if let true... = 0 {} //~ ERROR inclusive range with no end
     //~| ERROR only char and numeric types
-    if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported
+    if let .0... = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
-    //~| ERROR `...` range patterns are deprecated
     //~| ERROR mismatched types
 }
 
 fn exclusive_to() {
-    if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported
-    if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported
-    if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported
-    //~| ERROR only char and numeric types
-    if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported
+    if let ..0 = 0 {}
+    if let ..Y = 0 {}
+    if let ..true = 0 {}
+    //~^ ERROR only char and numeric types
+    if let .. .0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive_to() {
-    if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported
-    if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported
-    if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported
-    //~| ERROR only char and numeric types
-    if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported
+    if let ..=3 = 0 {}
+    if let ..=Y = 0 {}
+    if let ..=true = 0 {}
+    //~^ ERROR only char and numeric types
+    if let ..=.0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
 }
 
 fn inclusive2_to() {
-    if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
-    if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported
-    //~^ ERROR `...` range patterns are deprecated
+    if let ...3 = 0 {}
+    //~^ ERROR range-to patterns with `...` are not allowed
+    if let ...Y = 0 {}
+    //~^ ERROR range-to patterns with `...` are not allowed
+    if let ...true = 0 {}
+    //~^ ERROR range-to patterns with `...` are not allowed
     //~| ERROR only char and numeric types
-    if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported
+    if let ....3 = 0 {}
     //~^ ERROR float literals must have an integer part
-    //~| ERROR `...` range patterns are deprecated
+    //~| ERROR range-to patterns with `...` are not allowed
     //~| ERROR mismatched types
 }
 
@@ -136,14 +133,13 @@
 
     macro_rules! mac {
         ($e:expr) => {
-            let ..$e; //~ ERROR `..X` range patterns are not supported
-            let ...$e; //~ ERROR `...X` range patterns are not supported
-            //~^ ERROR `...` range patterns are deprecated
-            let ..=$e; //~ ERROR `..=X` range patterns are not supported
-            let $e..; //~ ERROR `X..` range patterns are not supported
-            let $e...; //~ ERROR `X...` range patterns are not supported
-            //~^ ERROR `...` range patterns are deprecated
-            let $e..=; //~ ERROR `X..=` range patterns are not supported
+            let ..$e;
+            let ...$e;
+            //~^ ERROR range-to patterns with `...` are not allowed
+            let ..=$e;
+            let $e..;
+            let $e...; //~ ERROR inclusive range with no end
+            let $e..=; //~ ERROR inclusive range with no end
         }
     }
 
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index 3fed64c..f43f9bf 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -1,377 +1,250 @@
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:24:16
    |
 LL |     if let X.. .0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:37:16
    |
 LL |     if let X..=.0 = 0 {}
    |                ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:49:12
+  --> $DIR/recover-range-pats.rs:50:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:52:17
+  --> $DIR/recover-range-pats.rs:53:17
    |
 LL |     if let X... .0 = 0 {}
    |                 ^^ help: must have an integer part: `0.0`
 
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:58:12
-   |
-LL |     if let 0.. = 0 {}
-   |            ^^^ help: try using the maximum value for the type: `0..MAX`
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:59:12
-   |
-LL |     if let X.. = 0 {}
-   |            ^^^ help: try using the maximum value for the type: `X..MAX`
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:60:12
-   |
-LL |     if let true.. = 0 {}
-   |            ^^^^^^ help: try using the maximum value for the type: `true..MAX`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:62:12
+  --> $DIR/recover-range-pats.rs:63:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:62:12
-   |
-LL |     if let .0.. = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0.0..MAX`
-
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:68:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:69:13
    |
 LL |     if let 0..= = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0..=MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:69:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:70:13
    |
 LL |     if let X..= = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `X..=MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:70:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:71:16
    |
 LL |     if let true..= = 0 {}
-   |            ^^^^^^^ help: try using the maximum value for the type: `true..=MAX`
+   |                ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:72:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:73:14
    |
 LL |     if let .0..= = 0 {}
-   |            ^^^^^ help: try using the maximum value for the type: `0.0..=MAX`
+   |              ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:78:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:79:13
    |
 LL |     if let 0... = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `0...MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:80:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:80:13
    |
 LL |     if let X... = 0 {}
-   |            ^^^^ help: try using the maximum value for the type: `X...MAX`
+   |             ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:82:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:81:16
    |
 LL |     if let true... = 0 {}
-   |            ^^^^^^^ help: try using the maximum value for the type: `true...MAX`
+   |                ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:85:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ help: must have an integer part: `0.0`
 
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:85:12
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:83:14
    |
 LL |     if let .0... = 0 {}
-   |            ^^^^^ help: try using the maximum value for the type: `0.0...MAX`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:92:12
+   |              ^^^ help: use `..` instead
    |
-LL |     if let ..0 = 0 {}
-   |            ^^^ help: try using the minimum value for the type: `MIN..0`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:93:12
-   |
-LL |     if let ..Y = 0 {}
-   |            ^^^ help: try using the minimum value for the type: `MIN..Y`
-
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:94:12
-   |
-LL |     if let ..true = 0 {}
-   |            ^^^^^^ help: try using the minimum value for the type: `MIN..true`
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:96:15
+  --> $DIR/recover-range-pats.rs:93:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:96:12
-   |
-LL |     if let .. .0 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN..0.0`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:102:12
-   |
-LL |     if let ..=3 = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN..=3`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:103:12
-   |
-LL |     if let ..=Y = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN..=Y`
-
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:104:12
-   |
-LL |     if let ..=true = 0 {}
-   |            ^^^^^^^ help: try using the minimum value for the type: `MIN..=true`
-
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:106:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ help: must have an integer part: `0.0`
 
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:106:12
-   |
-LL |     if let ..=.0 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN..=0.0`
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:112:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:109:12
    |
 LL |     if let ...3 = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN...3`
+   |            ^^^ help: use `..=` instead
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:114:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:111:12
    |
 LL |     if let ...Y = 0 {}
-   |            ^^^^ help: try using the minimum value for the type: `MIN...Y`
+   |            ^^^ help: use `..=` instead
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:116:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:113:12
    |
 LL |     if let ...true = 0 {}
-   |            ^^^^^^^ help: try using the minimum value for the type: `MIN...true`
+   |            ^^^ help: use `..=` instead
 
 error: float literals must have an integer part
-  --> $DIR/recover-range-pats.rs:119:15
+  --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ help: must have an integer part: `0.3`
 
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:119:12
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:116:12
    |
 LL |     if let ....3 = 0 {}
-   |            ^^^^^ help: try using the minimum value for the type: `MIN...0.3`
+   |            ^^^ help: use `..=` instead
 
-error: `..X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:139:17
-   |
-LL |             let ..$e;
-   |                 ^^ help: try using the minimum value for the type: `MIN..0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `...X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:140:17
+error: range-to patterns with `...` are not allowed
+  --> $DIR/recover-range-pats.rs:137:17
    |
 LL |             let ...$e;
-   |                 ^^^ help: try using the minimum value for the type: `MIN...0`
+   |                 ^^^ help: use `..=` instead
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
 
-error: `..=X` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:142:17
-   |
-LL |             let ..=$e;
-   |                 ^^^ help: try using the minimum value for the type: `MIN..=0`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `X..` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:143:19
-   |
-LL |             let $e..;
-   |                   ^^ help: try using the maximum value for the type: `0..MAX`
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `X...` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:144:19
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:141:19
    |
 LL |             let $e...;
-   |                   ^^^ help: try using the maximum value for the type: `0...MAX`
+   |                   ^^^ help: use `..` instead
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: `X..=` range patterns are not supported
-  --> $DIR/recover-range-pats.rs:146:19
+error[E0586]: inclusive range with no end
+  --> $DIR/recover-range-pats.rs:142:19
    |
 LL |             let $e..=;
-   |                   ^^^ help: try using the maximum value for the type: `0..=MAX`
+   |                   ^^^ help: use `..` instead
 ...
 LL |     mac!(0);
    |     -------- in this macro invocation
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:41:13
+  --> $DIR/recover-range-pats.rs:42:13
    |
 LL |     if let 0...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
 note: lint level defined here
-  --> $DIR/recover-range-pats.rs:7:9
+  --> $DIR/recover-range-pats.rs:8:9
    |
 LL | #![deny(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:42:13
+  --> $DIR/recover-range-pats.rs:43:13
    |
 LL |     if let 0...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:43:13
+  --> $DIR/recover-range-pats.rs:44:13
    |
 LL |     if let X...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:44:13
+  --> $DIR/recover-range-pats.rs:45:13
    |
 LL |     if let X...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:45:16
+  --> $DIR/recover-range-pats.rs:46:16
    |
 LL |     if let true...Y = 0 {}
    |                ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:47:13
+  --> $DIR/recover-range-pats.rs:48:13
    |
 LL |     if let X...true = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:49:14
+  --> $DIR/recover-range-pats.rs:50:14
    |
 LL |     if let .0...Y = 0 {}
    |              ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:52:13
+  --> $DIR/recover-range-pats.rs:53:13
    |
 LL |     if let X... .0 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
 
 error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:78:13
-   |
-LL |     if let 0... = 0 {}
-   |             ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:80:13
-   |
-LL |     if let X... = 0 {}
-   |             ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:82:16
-   |
-LL |     if let true... = 0 {}
-   |                ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:85:14
-   |
-LL |     if let .0... = 0 {}
-   |              ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:112:12
-   |
-LL |     if let ...3 = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:114:12
-   |
-LL |     if let ...Y = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:116:12
-   |
-LL |     if let ...true = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:119:12
-   |
-LL |     if let ....3 = 0 {}
-   |            ^^^ help: use `..=` for an inclusive range
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:129:20
+  --> $DIR/recover-range-pats.rs:126:20
    |
 LL |             let $e1...$e2;
    |                    ^^^ help: use `..=` for an inclusive range
@@ -379,26 +252,8 @@
 LL |     mac2!(0, 1);
    |     ------------ in this macro invocation
 
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:140:17
-   |
-LL |             let ...$e;
-   |                 ^^^ help: use `..=` for an inclusive range
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
-error: `...` range patterns are deprecated
-  --> $DIR/recover-range-pats.rs:144:19
-   |
-LL |             let $e...;
-   |                   ^^^ help: use `..=` for an inclusive range
-...
-LL |     mac!(0);
-   |     -------- in this macro invocation
-
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:19:12
+  --> $DIR/recover-range-pats.rs:20:12
    |
 LL |     if let true..Y = 0 {}
    |            ^^^^  - this is of type `u8`
@@ -406,7 +261,7 @@
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:20:15
+  --> $DIR/recover-range-pats.rs:21:15
    |
 LL |     if let X..true = 0 {}
    |            -  ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -414,7 +269,7 @@
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:21:12
+  --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
    |            ^^  - this is of type `u8`
@@ -422,7 +277,7 @@
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:23:16
+  --> $DIR/recover-range-pats.rs:24:16
    |
 LL |     if let X.. .0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -431,7 +286,7 @@
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:32:12
+  --> $DIR/recover-range-pats.rs:33:12
    |
 LL |     if let true..=Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -439,7 +294,7 @@
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:33:16
+  --> $DIR/recover-range-pats.rs:34:16
    |
 LL |     if let X..=true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -447,7 +302,7 @@
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:34:12
+  --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
    |            ^^   - this is of type `u8`
@@ -455,7 +310,7 @@
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:36:16
+  --> $DIR/recover-range-pats.rs:37:16
    |
 LL |     if let X..=.0 = 0 {}
    |            -   ^^   - this expression has type `u8`
@@ -464,7 +319,7 @@
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:45:12
+  --> $DIR/recover-range-pats.rs:46:12
    |
 LL |     if let true...Y = 0 {}
    |            ^^^^   - this is of type `u8`
@@ -472,7 +327,7 @@
    |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:47:16
+  --> $DIR/recover-range-pats.rs:48:16
    |
 LL |     if let X...true = 0 {}
    |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -480,7 +335,7 @@
    |            this is of type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:49:12
+  --> $DIR/recover-range-pats.rs:50:12
    |
 LL |     if let .0...Y = 0 {}
    |            ^^   - this is of type `u8`
@@ -488,7 +343,7 @@
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:52:17
+  --> $DIR/recover-range-pats.rs:53:17
    |
 LL |     if let X... .0 = 0 {}
    |            -    ^^   - this expression has type `u8`
@@ -497,78 +352,78 @@
    |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:60:12
+  --> $DIR/recover-range-pats.rs:61:12
    |
 LL |     if let true.. = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:62:12
+  --> $DIR/recover-range-pats.rs:63:12
    |
 LL |     if let .0.. = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:70:12
+  --> $DIR/recover-range-pats.rs:71:12
    |
 LL |     if let true..= = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:72:12
+  --> $DIR/recover-range-pats.rs:73:12
    |
 LL |     if let .0..= = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:82:12
+  --> $DIR/recover-range-pats.rs:81:12
    |
 LL |     if let true... = 0 {}
    |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:85:12
+  --> $DIR/recover-range-pats.rs:83:12
    |
 LL |     if let .0... = 0 {}
    |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:94:14
+  --> $DIR/recover-range-pats.rs:91:14
    |
 LL |     if let ..true = 0 {}
    |              ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:96:15
+  --> $DIR/recover-range-pats.rs:93:15
    |
 LL |     if let .. .0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:104:15
+  --> $DIR/recover-range-pats.rs:101:15
    |
 LL |     if let ..=true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:106:15
+  --> $DIR/recover-range-pats.rs:103:15
    |
 LL |     if let ..=.0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/recover-range-pats.rs:116:15
+  --> $DIR/recover-range-pats.rs:113:15
    |
 LL |     if let ...true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:119:15
+  --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ....3 = 0 {}
    |               ^^ expected integer, found floating-point number
 
-error: aborting due to 85 previous errors
+error: aborting due to 60 previous errors
 
-Some errors have detailed explanations: E0029, E0308.
+Some errors have detailed explanations: E0029, E0308, E0586.
 For more information about an error, try `rustc --explain E0029`.
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 9c7a25d..e27b03d 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.rs
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs
@@ -3,24 +3,26 @@
 
 fn main() {
     false == false == false;
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
 
     false == 0 < 2;
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
     f<X>();
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
     //~| HELP use `::<...>` instead of `<...>` to specify type arguments
 
     f<Result<Option<X>, Option<Option<X>>>(1, 2);
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
+    //~| HELP split the comparison into two...
+    //~| ...or parenthesize one of the comparisons
     //~| HELP use `::<...>` instead of `<...>` to specify type arguments
 
     use std::convert::identity;
     let _ = identity<u8>;
-    //~^ ERROR chained comparison operators require parentheses
+    //~^ ERROR comparison operators cannot be chained
     //~| HELP use `::<...>` instead of `<...>` to specify type arguments
     //~| HELP or use `(...)` if you meant to specify fn arguments
 }
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 bece9a3..44edf2d 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -1,16 +1,16 @@
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:5:11
    |
 LL |     false == false == false;
    |           ^^^^^^^^^^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:8:11
    |
 LL |     false == 0 < 2;
    |           ^^^^^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:13:6
    |
 LL |     f<X>();
@@ -21,19 +21,27 @@
 LL |     f::<X>();
    |      ^^
 
-error: chained comparison operators require parentheses
+error: comparison operators cannot be chained
   --> $DIR/require-parens-for-chained-comparison.rs:17:6
    |
 LL |     f<Result<Option<X>, Option<Option<X>>>(1, 2);
    |      ^^^^^^^^
    |
+help: split the comparison into two...
+   |
+LL |     f < Result && Result <Option<X>, Option<Option<X>>>(1, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+help: ...or parenthesize one of the comparisons
+   |
+LL |     (f < Result) <Option<X>, Option<Option<X>>>(1, 2);
+   |     ^^^^^^^^^^^^^^
 help: use `::<...>` instead of `<...>` to specify type arguments
    |
 LL |     f::<Result<Option<X>, Option<Option<X>>>(1, 2);
    |      ^^
 
-error: chained comparison operators require parentheses
-  --> $DIR/require-parens-for-chained-comparison.rs:22:21
+error: comparison operators cannot be chained
+  --> $DIR/require-parens-for-chained-comparison.rs:24:21
    |
 LL |     let _ = identity<u8>;
    |                     ^^^^
diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr
index 03fb764..4b9f494 100644
--- a/src/test/ui/parser/trait-object-trait-parens.stderr
+++ b/src/test/ui/parser/trait-object-trait-parens.stderr
@@ -33,6 +33,9 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/trait-object-trait-parens.rs:11:31
    |
+LL | fn main() {
+   |        - help: consider introducing lifetime `'a` here: `<'a>`
+...
 LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
    |                               ^^ undeclared lifetime
 
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.rs b/src/test/ui/parser/type-parameters-in-field-exprs.rs
index 1b8ed9f..6a3b2c1 100644
--- a/src/test/ui/parser/type-parameters-in-field-exprs.rs
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct Foo {
     x: isize,
     y: isize,
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.stderr b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
index 8f32fb0..306b475 100644
--- a/src/test/ui/parser/type-parameters-in-field-exprs.stderr
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
@@ -1,17 +1,17 @@
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:13:10
+  --> $DIR/type-parameters-in-field-exprs.rs:11:10
    |
 LL |     f.x::<isize>;
    |          ^^^^^^^
 
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:15:10
+  --> $DIR/type-parameters-in-field-exprs.rs:13:10
    |
 LL |     f.x::<>;
    |          ^^
 
 error: field expressions may not have generic arguments
-  --> $DIR/type-parameters-in-field-exprs.rs:17:7
+  --> $DIR/type-parameters-in-field-exprs.rs:15:7
    |
 LL |     f.x::();
    |       ^^^^^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
index 1d9f341..2cd375d 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
@@ -1,7 +1,6 @@
 // Test that moving on both sides of an `@` pattern is not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U; // Not copy!
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
index f3f8fd6..12ebcb7 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
@@ -1,53 +1,53 @@
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:12:9
+  --> $DIR/borrowck-move-and-move.rs:11:9
    |
 LL |     let a @ b = U;
    |         ^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:16:9
+  --> $DIR/borrowck-move-and-move.rs:15:9
    |
 LL |     let a @ (b, c) = (U, U);
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:20:9
+  --> $DIR/borrowck-move-and-move.rs:19:9
    |
 LL |     let a @ (b, c) = (u(), u());
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:25:9
+  --> $DIR/borrowck-move-and-move.rs:24:9
    |
 LL |         a @ Ok(b) | a @ Err(b) => {}
    |         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:25:21
+  --> $DIR/borrowck-move-and-move.rs:24:21
    |
 LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:37:9
+  --> $DIR/borrowck-move-and-move.rs:36:9
    |
 LL |         xs @ [a, .., b] => {}
    |         ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:43:9
+  --> $DIR/borrowck-move-and-move.rs:42:9
    |
 LL |         xs @ [_, ys @ .., _] => {}
    |         ^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:32:12
+  --> $DIR/borrowck-move-and-move.rs:31:12
    |
 LL |     fn fun(a @ b: U) {}
    |            ^^^^^ binds an already bound by-move value by moving it
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:12:13
+  --> $DIR/borrowck-move-and-move.rs:11:13
    |
 LL |     let a @ b = U;
    |         ----^   - move occurs because value has type `main::U`, which does not implement the `Copy` trait
@@ -56,7 +56,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:16:17
+  --> $DIR/borrowck-move-and-move.rs:15:17
    |
 LL |     let a @ (b, c) = (U, U);
    |         --------^-   ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -65,7 +65,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:20:17
+  --> $DIR/borrowck-move-and-move.rs:19:17
    |
 LL |     let a @ (b, c) = (u(), u());
    |         --------^-   ---------- move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -74,7 +74,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:16
+  --> $DIR/borrowck-move-and-move.rs:24:16
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -85,7 +85,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:29
+  --> $DIR/borrowck-move-and-move.rs:24:29
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -96,7 +96,7 @@
    |                     value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:37:22
+  --> $DIR/borrowck-move-and-move.rs:36:22
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait
@@ -107,7 +107,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:43:18
+  --> $DIR/borrowck-move-and-move.rs:42:18
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait
@@ -118,7 +118,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:32:16
+  --> $DIR/borrowck-move-and-move.rs:31:16
    |
 LL |     fn fun(a @ b: U) {}
    |            ----^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
index afac8d9..092bd11 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
@@ -4,7 +4,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
index fce3140..3b2f598 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
@@ -2,7 +2,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index 5772fad..e96c15b 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -1,23 +1,23 @@
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:17:9
+  --> $DIR/borrowck-pat-at-and-box.rs:16:9
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:21:9
+  --> $DIR/borrowck-pat-at-and-box.rs:20:9
    |
 LL |     let a @ box b = Box::new(C);
    |         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:33:25
+  --> $DIR/borrowck-pat-at-and-box.rs:32:25
    |
 LL |     match Box::new(C) { a @ box b => {} }
    |                         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:37:21
+  --> $DIR/borrowck-pat-at-and-box.rs:36:21
    |
 LL |     let ref a @ box b = Box::new(NC);
    |         ------------^
@@ -26,7 +26,7 @@
    |         by-ref pattern here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:39:9
+  --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(nc());
    |         -----^^^^^^^---------
@@ -35,7 +35,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:41:9
+  --> $DIR/borrowck-pat-at-and-box.rs:40:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -44,7 +44,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:43:9
+  --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -53,7 +53,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:9
+  --> $DIR/borrowck-pat-at-and-box.rs:45:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -62,7 +62,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:9
+  --> $DIR/borrowck-pat-at-and-box.rs:51:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ---------^^^^^^^-----
@@ -71,7 +71,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:9
+  --> $DIR/borrowck-pat-at-and-box.rs:65:9
    |
 LL |         ref mut a @ box ref b => {
    |         ---------^^^^^^^-----
@@ -80,7 +80,7 @@
    |         mutable borrow occurs here
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:75:38
+  --> $DIR/borrowck-pat-at-and-box.rs:74:38
    |
 LL |         box [Ok(a), ref xs @ .., Err(b)] => {}
    |                     -----------      ^ by-move pattern here
@@ -88,7 +88,7 @@
    |                     by-ref pattern here
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:81:46
+  --> $DIR/borrowck-pat-at-and-box.rs:80:46
    |
 LL |         [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {}
    |                 -----   -----------          ^           --------- by-ref pattern here
@@ -98,19 +98,19 @@
    |                 by-ref pattern here
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:25:11
+  --> $DIR/borrowck-pat-at-and-box.rs:24:11
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:29:11
+  --> $DIR/borrowck-pat-at-and-box.rs:28:11
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:11
+  --> $DIR/borrowck-pat-at-and-box.rs:57:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ---------^^^^^^^-----
@@ -119,7 +119,7 @@
    |           mutable borrow occurs here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:17:18
+  --> $DIR/borrowck-pat-at-and-box.rs:16:18
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ---------^   ------------ move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait
@@ -128,7 +128,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:21:17
+  --> $DIR/borrowck-pat-at-and-box.rs:20:17
    |
 LL |     let a @ box b = Box::new(C);
    |         --------^   ----------- move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
@@ -137,7 +137,7 @@
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:33:33
+  --> $DIR/borrowck-pat-at-and-box.rs:32:33
    |
 LL |     match Box::new(C) { a @ box b => {} }
    |           -----------   --------^
@@ -147,7 +147,7 @@
    |           move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:21
+  --> $DIR/borrowck-pat-at-and-box.rs:45:21
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         ------------^^^^^^^^^
@@ -159,7 +159,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:25
+  --> $DIR/borrowck-pat-at-and-box.rs:51:25
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ----------------^^^^^
@@ -171,7 +171,7 @@
    |     -- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:25
+  --> $DIR/borrowck-pat-at-and-box.rs:65:25
    |
 LL |         ref mut a @ box ref b => {
    |         ----------------^^^^^
@@ -183,7 +183,7 @@
    |             -- mutable borrow later used here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:25:20
+  --> $DIR/borrowck-pat-at-and-box.rs:24:20
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ---------^
@@ -193,7 +193,7 @@
    |           move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:29:19
+  --> $DIR/borrowck-pat-at-and-box.rs:28:19
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           --------^
@@ -203,7 +203,7 @@
    |           move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:27
+  --> $DIR/borrowck-pat-at-and-box.rs:57:27
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ----------------^^^^^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
index be19e5f..c4ce50c 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
@@ -2,7 +2,6 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
-#![feature(slice_patterns)]
 #![feature(bindings_after_at)]
 
 #[derive(Copy, Clone)]
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
index edf9fb3..fb24301 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
@@ -4,7 +4,6 @@
 // of an `@` pattern according to NLL borrowck.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U; // Not copy!
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
index 88eda9a..e8510df 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
@@ -1,5 +1,4 @@
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 enum Option<T> {
     None,
@@ -101,6 +100,7 @@
         //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
         //~| ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
         //~| ERROR cannot move out of `b` in pattern guard
+        //~| ERROR cannot move out of `b` in pattern guard
         _ => {}
     }
     match Ok(U) {
@@ -108,6 +108,7 @@
         //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
         //~| ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
         //~| ERROR cannot move out of `a` in pattern guard
+        //~| ERROR cannot move out of `a` in pattern guard
         _ => {}
     }
 
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index b068a61..0d7b703 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow `z` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ---------^^^^^^^^^^^^^-----^
@@ -8,7 +8,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:9
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         ---------^^^^-----------------^
@@ -18,7 +18,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `b` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      -----^^^---------
@@ -27,7 +27,7 @@
    |                      immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:36:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -36,7 +36,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -45,7 +45,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -55,7 +55,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -65,7 +65,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9
    |
 LL |     let ref mut a @ ref b = u();
    |         ---------^^^-----
@@ -74,7 +74,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:9
    |
 LL |     let ref a @ ref mut b = u();
    |         -----^^^---------
@@ -83,7 +83,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:56:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:55:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -92,7 +92,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:60:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -101,7 +101,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         ---------^^^^^^-----^
@@ -110,7 +110,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 ---------^^^^^^^-----^
@@ -119,7 +119,7 @@
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----^^^^^^---------^
@@ -128,7 +128,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 -----^^^^^^^---------^
@@ -137,7 +137,7 @@
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |         -----^^^^^^---------^
@@ -146,7 +146,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                 -----^^^^^^^---------^
@@ -155,7 +155,7 @@
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |         ---------^^^^^^-----^
@@ -164,7 +164,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -173,7 +173,7 @@
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |         -----^^^^^^---------^
@@ -182,7 +182,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                 -----^^^^^^^---------^
@@ -209,7 +209,7 @@
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:114:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:115:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -219,7 +219,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -229,7 +229,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:126:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -239,7 +239,7 @@
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:132:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -249,7 +249,7 @@
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
    |
 LL |     fn f1(ref a @ ref mut b: U) {}
    |           -----^^^---------
@@ -258,7 +258,7 @@
    |           immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
    |
 LL |     fn f2(ref mut a @ ref b: U) {}
    |           ---------^^^-----
@@ -267,7 +267,7 @@
    |           mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
    |
 LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           -----^^^^^^^^^^^----------------^^^^^^^^
@@ -276,7 +276,7 @@
    |           immutable borrow occurs here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ----------------------^^^^^-
@@ -288,7 +288,7 @@
    |             ---------- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:21
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:21
    |
 LL |     let ref mut a @ ref b = u();
    |         ------------^^^^^
@@ -300,7 +300,7 @@
    |     -------- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:17
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:17
    |
 LL |     let ref a @ ref mut b = u();
    |         --------^^^^^^^^^
@@ -312,7 +312,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:20
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:20
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----------^^^^^^^^^-
@@ -324,7 +324,7 @@
    |                  - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:45
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:45
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 ------------^^^^^^^^^-
@@ -336,7 +336,7 @@
    |                  - immutable borrow later used here
 
 error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:61
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                                             ^^^^^^ cannot assign
@@ -344,7 +344,7 @@
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:61
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                                             ^^^^^^^^^^^ cannot assign
@@ -352,7 +352,15 @@
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66
+   |
+LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
+   |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error[E0507]: cannot move out of `b` in pattern guard
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
@@ -367,8 +375,16 @@
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
+error[E0507]: cannot move out of `a` in pattern guard
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66
+   |
+LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
+   |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -380,7 +396,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -392,7 +408,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:126:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -404,7 +420,7 @@
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:126:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -415,7 +431,7 @@
 LL |     drop(a);
    |          - immutable borrow later used here
 
-error: aborting due to 43 previous errors
+error: aborting due to 45 previous errors
 
 Some errors have detailed explanations: E0502, E0507, E0594.
 For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
index 6b8b754..f425b35 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
@@ -1,7 +1,6 @@
 // Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index 1b5e6c7..d07ad14 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:25:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -8,7 +8,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -17,7 +17,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -26,7 +26,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -35,7 +35,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -44,7 +44,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:43:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -66,7 +66,7 @@
    | |_____^
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:53:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:52:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -88,31 +88,31 @@
    | |_________^
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:63:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:62:9
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:71:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:9
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:79:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -121,7 +121,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:79:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -130,7 +130,7 @@
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:85:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -139,7 +139,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:85:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -148,7 +148,7 @@
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -157,7 +157,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -166,7 +166,7 @@
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -175,7 +175,7 @@
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -184,7 +184,7 @@
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:11:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
    |
 LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -193,7 +193,7 @@
    |           first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
    |
 LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -202,7 +202,7 @@
    |           first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:16:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
    |
 LL |           ref mut a @ [
    |           ^--------
@@ -220,7 +220,7 @@
    | |_________^
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:25:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -232,7 +232,7 @@
    |          - first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -244,7 +244,7 @@
    |     ------ first borrow later used here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:63:25
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:62:25
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ----------------^^^^^^^^^-   ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -253,7 +253,7 @@
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:21
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ------------^--   -------- move occurs because value has type `&mut (main::U, [main::U; 2])`, which does not implement the `Copy` trait
@@ -262,7 +262,7 @@
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:71:18
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:18
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ---------^^^^^^^^^   ------ move occurs because value has type `&mut main::U`, which does not implement the `Copy` trait
@@ -271,7 +271,7 @@
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:30
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:30
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ---------------------^^^^^^^^^-   ----------- move occurs because value has type `&mut (main::U, main::U)`, which does not implement the `Copy` trait
@@ -280,7 +280,7 @@
    |         value moved here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -292,7 +292,7 @@
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
@@ -304,7 +304,7 @@
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -316,7 +316,7 @@
    |                  - first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
index 7a0f144..d0018ce 100644
--- a/src/test/ui/pattern/const-pat-ice.stderr
+++ b/src/test/ui/pattern/const-pat-ice.stderr
@@ -1,5 +1,5 @@
-thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:LL:CC
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir_build/hair/pattern/_match.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/pattern/issue-67776-match-same-name-enum-variant-refs.stderr b/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
index abb8d69..21218d9 100644
--- a/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
+++ b/src/test/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr
@@ -3,6 +3,8 @@
    |
 LL |         Bar => {},
    |         ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
+   |
+   = note: `#[warn(bindings_with_variant_name)]` on by default
 
 warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
   --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:19:9
diff --git a/src/test/ui/pattern/issue-68393-let-pat-assoc-constant.rs b/src/test/ui/pattern/issue-68393-let-pat-assoc-constant.rs
new file mode 100644
index 0000000..95ead6b
--- /dev/null
+++ b/src/test/ui/pattern/issue-68393-let-pat-assoc-constant.rs
@@ -0,0 +1,26 @@
+pub enum EFoo {
+    A,
+}
+
+pub trait Foo {
+    const X: EFoo;
+}
+
+struct Abc;
+
+impl Foo for Abc {
+    const X: EFoo = EFoo::A;
+}
+
+struct Def;
+impl Foo for Def {
+    const X: EFoo = EFoo::A;
+}
+
+pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
+    //~^ ERROR associated consts cannot be referenced in patterns
+    let A::X = arg;
+    //~^ ERROR associated consts cannot be referenced in patterns
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/issue-68393-let-pat-assoc-constant.stderr b/src/test/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
new file mode 100644
index 0000000..54ecc24
--- /dev/null
+++ b/src/test/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
@@ -0,0 +1,15 @@
+error[E0158]: associated consts cannot be referenced in patterns
+  --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40
+   |
+LL | pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
+   |                                        ^^^^
+
+error[E0158]: associated consts cannot be referenced in patterns
+  --> $DIR/issue-68393-let-pat-assoc-constant.rs:22:9
+   |
+LL |     let A::X = arg;
+   |         ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0158`.
diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs
new file mode 100644
index 0000000..f10a7f2
--- /dev/null
+++ b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let x = 255u8;
+    let 0u8..=x = 0;
+    //~^ ERROR runtime values cannot be referenced in patterns
+}
diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr
new file mode 100644
index 0000000..c1508bd
--- /dev/null
+++ b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr
@@ -0,0 +1,9 @@
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/issue-68394-let-pat-runtime-value.rs:3:15
+   |
+LL |     let 0u8..=x = 0;
+   |               ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/pattern/issue-68396-let-float-bug.rs b/src/test/ui/pattern/issue-68396-let-float-bug.rs
new file mode 100644
index 0000000..afc599a
--- /dev/null
+++ b/src/test/ui/pattern/issue-68396-let-float-bug.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let 1234567890123456789012345678901234567890e-340: f64 = 0.0;
+    //~^ ERROR could not evaluate float literal (see issue #31407)
+
+    fn param(1234567890123456789012345678901234567890e-340: f64) {}
+    //~^ ERROR could not evaluate float literal (see issue #31407)
+}
diff --git a/src/test/ui/pattern/issue-68396-let-float-bug.stderr b/src/test/ui/pattern/issue-68396-let-float-bug.stderr
new file mode 100644
index 0000000..618aa4b
--- /dev/null
+++ b/src/test/ui/pattern/issue-68396-let-float-bug.stderr
@@ -0,0 +1,15 @@
+error[E0080]: could not evaluate float literal (see issue #31407)
+  --> $DIR/issue-68396-let-float-bug.rs:2:9
+   |
+LL |     let 1234567890123456789012345678901234567890e-340: f64 = 0.0;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0080]: could not evaluate float literal (see issue #31407)
+  --> $DIR/issue-68396-let-float-bug.rs:5:14
+   |
+LL |     fn param(1234567890123456789012345678901234567890e-340: f64) {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.rs b/src/test/ui/pattern/patkind-litrange-no-expr.rs
index def6c62..5b3db2e 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.rs
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.rs
@@ -18,7 +18,8 @@
     Pos = 1,
     Neg = -1,
     Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
-                   //~^ ERROR only char and numeric types are allowed in range patterns
+                   //~| ERROR arbitrary expressions aren't allowed in patterns
+                   //~| ERROR only char and numeric types are allowed in range patterns
 });
 
 fn main() {}
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
index 78768d2..70dd1a9 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
@@ -4,6 +4,12 @@
 LL |     Arith = 1 + 1,
    |             ^^^^^
 
+error: arbitrary expressions aren't allowed in patterns
+  --> $DIR/patkind-litrange-no-expr.rs:20:13
+   |
+LL |     Arith = 1 + 1,
+   |             ^^^^^
+
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/patkind-litrange-no-expr.rs:20:13
    |
@@ -13,6 +19,6 @@
 LL |     Arith = 1 + 1,
    |             ^^^^^ this is of type `_` but it should be `char` or numeric
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0029`.
diff --git a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
similarity index 65%
rename from src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs
rename to src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
index c910cde..5b0482d 100644
--- a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs
+++ b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
@@ -1,8 +1,6 @@
 // check-pass
 
-// This used to cause a stack overflow in the compiler.
-
-#![feature(slice_patterns)]
+// This used to cause a stack overflow during exhaustiveness checking in the compiler.
 
 fn main() {
     const LARGE_SIZE: usize = 1024 * 1024;
diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
similarity index 89%
rename from src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs
rename to src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
index 6c54c93..54dfa88 100644
--- a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs
+++ b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(slice_patterns)]
+
 #![deny(unreachable_patterns)]
 
 const C0: &'static [u8] = b"\x00";
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
index 7541ea3..9b6c8bd 100644
--- a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
index b28646b..0948469 100644
--- a/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
@@ -1,53 +1,53 @@
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:9:9
+  --> $DIR/match-byte-array-patterns.rs:8:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/match-byte-array-patterns.rs:2:9
+  --> $DIR/match-byte-array-patterns.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:15:9
+  --> $DIR/match-byte-array-patterns.rs:14:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:21:9
+  --> $DIR/match-byte-array-patterns.rs:20:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:27:9
+  --> $DIR/match-byte-array-patterns.rs:26:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:35:9
+  --> $DIR/match-byte-array-patterns.rs:34:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:41:9
+  --> $DIR/match-byte-array-patterns.rs:40:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:47:9
+  --> $DIR/match-byte-array-patterns.rs:46:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:53:9
+  --> $DIR/match-byte-array-patterns.rs:52:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
index 7de7b7e..37c4ccd 100644
--- a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
+++ b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
@@ -34,11 +34,15 @@
       //~^ WARNING floating-point types cannot be used in patterns
       //~| WARNING floating-point types cannot be used in patterns
       //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       0.02f64 => {} //~ ERROR unreachable pattern
       //~^ WARNING floating-point types cannot be used in patterns
+      //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING this was previously accepted by the compiler
       //~| WARNING this was previously accepted by the compiler
       _ => {}
     };
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
index c15186d..8412a11 100644
--- a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
+++ b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
@@ -48,7 +48,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 warning: floating-point types cannot be used in patterns
-  --> $DIR/match-range-fail-dominate.rs:40:7
+  --> $DIR/match-range-fail-dominate.rs:42:7
    |
 LL |       0.02f64 => {}
    |       ^^^^^^^
@@ -57,7 +57,7 @@
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
 error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:40:7
+  --> $DIR/match-range-fail-dominate.rs:42:7
    |
 LL |       0.02f64 => {}
    |       ^^^^^^^
@@ -71,5 +71,23 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:33:19
+   |
+LL |       0.01f64 ..= 6.5f64 => {}
+   |                   ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:42:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.rs b/src/test/ui/pattern/usefulness/match-slice-patterns.rs
index af7fd53..92d74b8 100644
--- a/src/test/ui/pattern/usefulness/match-slice-patterns.rs
+++ b/src/test/ui/pattern/usefulness/match-slice-patterns.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn check(list: &[Option<()>]) {
     match list {
     //~^ ERROR `&[_, Some(_), .., None, _]` not covered
diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
index 72ae5d5..977a112 100644
--- a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
+++ b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
-  --> $DIR/match-slice-patterns.rs:4:11
+  --> $DIR/match-slice-patterns.rs:2:11
    |
 LL |     match list {
    |           ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
diff --git a/src/test/ui/pattern/usefulness/match-vec-unreachable.rs b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
index 7881052..3342389 100644
--- a/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
+++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
index 415c24a..e9a7510 100644
--- a/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
+++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
@@ -1,23 +1,23 @@
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:9:9
+  --> $DIR/match-vec-unreachable.rs:8:9
    |
 LL |         [(1, 2), (2, 3), b] => (),
    |         ^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/match-vec-unreachable.rs:2:9
+  --> $DIR/match-vec-unreachable.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:19:9
+  --> $DIR/match-vec-unreachable.rs:18:9
    |
 LL |         [_, _, _, _, _] => { }
    |         ^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:27:9
+  --> $DIR/match-vec-unreachable.rs:26:9
    |
 LL |         ['a', 'b', 'c'] => {}
    |         ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
index 9423a28..d198144 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 enum T { A(U), B }
 enum U { C, D }
 
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
index 67c818e..72b4b52 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
-  --> $DIR/non-exhaustive-match-nested.rs:7:11
+  --> $DIR/non-exhaustive-match-nested.rs:5:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
@@ -7,7 +7,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `A(C)` not covered
-  --> $DIR/non-exhaustive-match-nested.rs:17:11
+  --> $DIR/non-exhaustive-match-nested.rs:15:11
    |
 LL | enum T { A(U), B }
    | ------------------
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
index bfca535..9947989 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![allow(illegal_floating_point_literal_pattern)]
 
 enum T { A, B }
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
index 577867e..a06ad57 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `A` not covered
-  --> $DIR/non-exhaustive-match.rs:8:11
+  --> $DIR/non-exhaustive-match.rs:7:11
    |
 LL | enum T { A, B }
    | ---------------
@@ -13,7 +13,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `false` not covered
-  --> $DIR/non-exhaustive-match.rs:9:11
+  --> $DIR/non-exhaustive-match.rs:8:11
    |
 LL |     match true {
    |           ^^^^ pattern `false` not covered
@@ -21,7 +21,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/non-exhaustive-match.rs:12:11
+  --> $DIR/non-exhaustive-match.rs:11:11
    |
 LL |     match Some(10) {
    |           ^^^^^^^^ pattern `Some(_)` not covered
@@ -29,7 +29,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
-  --> $DIR/non-exhaustive-match.rs:15:11
+  --> $DIR/non-exhaustive-match.rs:14:11
    |
 LL |     match (2, 3, 4) {
    |           ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
@@ -37,7 +37,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(A, A)` not covered
-  --> $DIR/non-exhaustive-match.rs:19:11
+  --> $DIR/non-exhaustive-match.rs:18:11
    |
 LL |     match (T::A, T::A) {
    |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
@@ -45,7 +45,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `B` not covered
-  --> $DIR/non-exhaustive-match.rs:23:11
+  --> $DIR/non-exhaustive-match.rs:22:11
    |
 LL | enum T { A, B }
    | ---------------
@@ -59,7 +59,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/non-exhaustive-match.rs:34:11
+  --> $DIR/non-exhaustive-match.rs:33:11
    |
 LL |     match *vec {
    |           ^^^^ pattern `[]` not covered
@@ -67,7 +67,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
-  --> $DIR/non-exhaustive-match.rs:47:11
+  --> $DIR/non-exhaustive-match.rs:46:11
    |
 LL |     match *vec {
    |           ^^^^ pattern `[_, _, _, _, ..]` not covered
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
index 4ca1cbc..abb4ea8 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 struct Foo {
     first: bool,
     second: Option<[usize; 4]>
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
index a0b497d..2a9fa07 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:9:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:7:11
    |
 LL | / struct Foo {
 LL | |     first: bool,
@@ -13,7 +13,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Red` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:25:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:23:11
    |
 LL | / enum Color {
 LL | |     Red,
@@ -29,7 +29,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:37:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:35:11
    |
 LL | / enum Direction {
 LL | |     North, East, South, West
@@ -46,7 +46,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:46:11
    |
 LL | / enum ExcessiveEnum {
 LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
@@ -59,7 +59,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:56:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:54:11
    |
 LL | / enum Color {
 LL | |     Red,
@@ -75,7 +75,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:72:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:70:11
    |
 LL |     match *x {
    |           ^^ pattern `[Second(true), Second(false)]` not covered
@@ -83,7 +83,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((), false)` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:85:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:83:11
    |
 LL |     match ((), false) {
    |           ^^^^^^^^^^^ pattern `((), false)` not covered
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
index 41ba2cc..52d1320 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     let s: &[bool] = &[true; 0];
     let s1: &[bool; 1] = &[false; 1];
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
index 8cb342f..b3701ef 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
+++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[false, _]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:10:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:8:11
    |
 LL |     match s2 {
    |           ^^ pattern `&[false, _]` not covered
@@ -7,7 +7,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:14:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:12:11
    |
 LL |     match s3 {
    |           ^^ pattern `&[false, ..]` not covered
@@ -15,7 +15,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:18:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:16:11
    |
 LL |     match s10 {
    |           ^^^ pattern `&[false, ..]` not covered
@@ -23,7 +23,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:27:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:25:11
    |
 LL |     match s2 {
    |           ^^ pattern `&[false, true]` not covered
@@ -31,7 +31,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:32:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:30:11
    |
 LL |     match s3 {
    |           ^^ pattern `&[false, .., true]` not covered
@@ -39,7 +39,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:37:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:35:11
    |
 LL |     match s {
    |           ^ pattern `&[false, .., true]` not covered
@@ -47,7 +47,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:44:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:42:11
    |
 LL |     match s {
    |           ^ pattern `&[_, ..]` not covered
@@ -55,7 +55,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:48:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:46:11
    |
 LL |     match s {
    |           ^ pattern `&[_, _, ..]` not covered
@@ -63,7 +63,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:53:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:51:11
    |
 LL |     match s {
    |           ^ pattern `&[false, ..]` not covered
@@ -71,7 +71,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:58:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:56:11
    |
 LL |     match s {
    |           ^ pattern `&[false, _, ..]` not covered
@@ -79,7 +79,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:64:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:62:11
    |
 LL |     match s {
    |           ^ pattern `&[_, .., false]` not covered
@@ -87,7 +87,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:71:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:69:11
    |
 LL |     match s {
    |           ^ pattern `&[_, _, .., true]` not covered
@@ -95,7 +95,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:78:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:76:11
    |
 LL |     match s {
    |           ^ pattern `&[true, _, .., _]` not covered
@@ -103,7 +103,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:87:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:85:11
    |
 LL |     match s {
    |           ^ pattern `&[..]` not covered
@@ -111,7 +111,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:91:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:89:11
    |
 LL |     match s {
    |           ^ pattern `&[true]` not covered
@@ -119,7 +119,7 @@
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:99:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:97:11
    |
 LL |     match s1 {
    |           ^^ pattern `&[false]` not covered
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs b/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
index 3b716ba..cbf64e2 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let s: &[bool] = &[true; 0];
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
index cd229a0..7c747b5 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr b/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
index 333ce17..e24d102 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
+++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
@@ -1,41 +1,41 @@
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:9:9
+  --> $DIR/slice-patterns-reachability.rs:8:9
    |
 LL |         [true, ..] => {}
    |         ^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/slice-patterns-reachability.rs:2:9
+  --> $DIR/slice-patterns-reachability.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:10:9
+  --> $DIR/slice-patterns-reachability.rs:9:9
    |
 LL |         [true] => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:15:9
+  --> $DIR/slice-patterns-reachability.rs:14:9
    |
 LL |         [.., true] => {}
    |         ^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:16:9
+  --> $DIR/slice-patterns-reachability.rs:15:9
    |
 LL |         [true] => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:21:9
+  --> $DIR/slice-patterns-reachability.rs:20:9
    |
 LL |         [false, .., true] => {}
    |         ^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:22:9
+  --> $DIR/slice-patterns-reachability.rs:21:9
    |
 LL |         [false, true] => {}
    |         ^^^^^^^^^^^^^
diff --git a/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr
index 5b0c930..0115fc0 100644
--- a/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr
+++ b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr
@@ -1,8 +1,10 @@
 error: unreachable pattern
   --> $DIR/struct-pattern-match-useless.rs:12:9
    |
+LL |         Foo { x: _x, y: _y } => (),
+   |         -------------------- matches any value
 LL |         Foo { .. } => ()
-   |         ^^^^^^^^^^
+   |         ^^^^^^^^^^ unreachable pattern
    |
 note: lint level defined here
   --> $DIR/struct-pattern-match-useless.rs:1:9
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 27b8600..b663ccc 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
@@ -9,6 +9,12 @@
 LL |     }
 LL |     1u32
    |     ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
@@ -21,6 +27,12 @@
 LL |     } else {
 LL |         return 1u32;
    |                ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
@@ -33,6 +45,12 @@
 LL |     } else {
 LL |         1u32
    |         ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
@@ -57,6 +75,12 @@
    |                     ---- ...is found to be `i32` here
 LL |         _ => 1u32,
    |              ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
@@ -71,6 +95,12 @@
 LL | |         _ => 2u32,
 LL | |     }
    | |_____^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
@@ -83,6 +113,12 @@
 ...
 LL |             1u32
    |             ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/privacy/decl-macro.stderr b/src/test/ui/privacy/decl-macro.stderr
index 230cf95..ae2e1b4 100644
--- a/src/test/ui/privacy/decl-macro.stderr
+++ b/src/test/ui/privacy/decl-macro.stderr
@@ -2,7 +2,13 @@
   --> $DIR/decl-macro.rs:8:8
    |
 LL |     m::mac!();
-   |        ^^^
+   |        ^^^ this macro is private
+   |
+note: the macro `mac` is defined here
+  --> $DIR/decl-macro.rs:4:5
+   |
+LL |     macro mac() {}
+   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/privacy-in-paths.stderr b/src/test/ui/privacy/privacy-in-paths.stderr
index 4b9faca..8860d8f 100644
--- a/src/test/ui/privacy/privacy-in-paths.stderr
+++ b/src/test/ui/privacy/privacy-in-paths.stderr
@@ -2,19 +2,37 @@
   --> $DIR/privacy-in-paths.rs:24:16
    |
 LL |         ::foo::bar::baz::f();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/privacy-in-paths.rs:3:5
+   |
+LL |     mod bar {
+   |     ^^^^^^^
 
 error[E0603]: module `bar` is private
   --> $DIR/privacy-in-paths.rs:25:16
    |
 LL |         ::foo::bar::S::f();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/privacy-in-paths.rs:3:5
+   |
+LL |     mod bar {
+   |     ^^^^^^^
 
 error[E0603]: trait `T` is private
   --> $DIR/privacy-in-paths.rs:26:23
    |
 LL |         <() as ::foo::T>::Assoc::f();
-   |                       ^
+   |                       ^ this trait is private
+   |
+note: the trait `T` is defined here
+  --> $DIR/privacy-in-paths.rs:8:5
+   |
+LL |     trait T {
+   |     ^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr
index 2871573..8b12109 100644
--- a/src/test/ui/privacy/privacy-ns2.stderr
+++ b/src/test/ui/privacy/privacy-ns2.stderr
@@ -58,19 +58,37 @@
   --> $DIR/privacy-ns2.rs:63:15
    |
 LL |     use foo3::Bar;
-   |               ^^^
+   |               ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:67:15
    |
 LL |     use foo3::Bar;
-   |               ^^^
+   |               ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:74:16
    |
 LL |     use foo3::{Bar,Baz};
-   |                ^^^
+   |                ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0107]: wrong number of const arguments: expected 0, found 1
   --> $DIR/privacy-ns2.rs:41:18
diff --git a/src/test/ui/privacy/privacy-ufcs.stderr b/src/test/ui/privacy/privacy-ufcs.stderr
index 6be14df..08640b8 100644
--- a/src/test/ui/privacy/privacy-ufcs.stderr
+++ b/src/test/ui/privacy/privacy-ufcs.stderr
@@ -2,7 +2,13 @@
   --> $DIR/privacy-ufcs.rs:12:20
    |
 LL |     <i32 as ::foo::Bar>::baz();
-   |                    ^^^
+   |                    ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ufcs.rs:4:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs
index d376237..fcf7b19 100644
--- a/src/test/ui/privacy/privacy1.rs
+++ b/src/test/ui/privacy/privacy1.rs
@@ -131,6 +131,7 @@
     fn test2() {
         use bar::baz::{foo, bar};
         //~^ ERROR: module `baz` is private
+        //~| ERROR: module `baz` is private
 
         foo();
         bar();
diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr
index b647cc8..215df0d 100644
--- a/src/test/ui/privacy/privacy1.stderr
+++ b/src/test/ui/privacy/privacy1.stderr
@@ -2,73 +2,157 @@
   --> $DIR/privacy1.rs:132:18
    |
 LL |         use bar::baz::{foo, bar};
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:140:18
+  --> $DIR/privacy1.rs:132:18
+   |
+LL |         use bar::baz::{foo, bar};
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
+
+error[E0603]: module `baz` is private
+  --> $DIR/privacy1.rs:141:18
    |
 LL |         use bar::baz;
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `i` is private
-  --> $DIR/privacy1.rs:164:20
+  --> $DIR/privacy1.rs:165:20
    |
 LL |     use self::foo::i::A;
-   |                    ^
+   |                    ^ this module is private
+   |
+note: the module `i` is defined here
+  --> $DIR/privacy1.rs:170:9
+   |
+LL |         mod i {
+   |         ^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:104:16
    |
 LL |         ::bar::baz::A::foo();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:105:16
    |
 LL |         ::bar::baz::A::bar();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:107:16
    |
 LL |         ::bar::baz::A.foo2();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:108:16
    |
 LL |         ::bar::baz::A.bar2();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:112:16
    |
 LL |         ::bar::B::foo();
-   |                ^
+   |                ^ this trait is private
+   |
+note: the trait `B` is defined here
+  --> $DIR/privacy1.rs:40:5
+   |
+LL |     trait B {
+   |     ^^^^^^^
 
 error[E0603]: function `epriv` is private
   --> $DIR/privacy1.rs:118:20
    |
 LL |             ::bar::epriv();
-   |                    ^^^^^
+   |                    ^^^^^ this function is private
+   |
+note: the function `epriv` is defined here
+  --> $DIR/privacy1.rs:65:9
+   |
+LL |         fn epriv();
+   |         ^^^^^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:127:16
    |
 LL |         ::bar::baz::foo();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:128:16
    |
 LL |         ::bar::baz::bar();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: trait `B` is private
-  --> $DIR/privacy1.rs:156:17
+  --> $DIR/privacy1.rs:157:17
    |
 LL |     impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
-   |                 ^
+   |                 ^ this trait is private
+   |
+note: the trait `B` is defined here
+  --> $DIR/privacy1.rs:40:5
+   |
+LL |     trait B {
+   |     ^^^^^^^
 
 error[E0624]: method `bar` is private
   --> $DIR/privacy1.rs:77:9
@@ -100,7 +184,7 @@
 LL |         ::bar::baz::A.bar2();
    |                       ^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
 
 Some errors have detailed explanations: E0603, E0624.
 For more information about an error, try `rustc --explain E0603`.
diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr
index 9f23596..719dc27 100644
--- a/src/test/ui/privacy/privacy2.stderr
+++ b/src/test/ui/privacy/privacy2.stderr
@@ -4,11 +4,17 @@
 LL |     use bar::foo;
    |         ^^^^^^^^ no `foo` in `bar`
 
-error[E0603]: function `foo` is private
+error[E0603]: function import `foo` is private
   --> $DIR/privacy2.rs:23:20
    |
 LL |     use bar::glob::foo;
-   |                    ^^^
+   |                    ^^^ this function import is private
+   |
+note: the function import `foo` is defined here
+  --> $DIR/privacy2.rs:10:13
+   |
+LL |         use foo;
+   |             ^^^
 
 error: requires `sized` lang_item
 
diff --git a/src/test/ui/privacy/privacy4.stderr b/src/test/ui/privacy/privacy4.stderr
index e4a20f9..e34b2d5 100644
--- a/src/test/ui/privacy/privacy4.stderr
+++ b/src/test/ui/privacy/privacy4.stderr
@@ -2,7 +2,13 @@
   --> $DIR/privacy4.rs:21:14
    |
 LL |     use bar::glob::gpriv;
-   |              ^^^^
+   |              ^^^^ this module is private
+   |
+note: the module `glob` is defined here
+  --> $DIR/privacy4.rs:13:5
+   |
+LL |     mod glob {
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr
index 2ee8314..197a857 100644
--- a/src/test/ui/privacy/privacy5.stderr
+++ b/src/test/ui/privacy/privacy5.stderr
@@ -5,7 +5,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a = a::A(());
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:52:16
@@ -14,7 +20,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let b = a::B(2);
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:53:16
@@ -23,7 +35,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let c = a::C(2, 3);
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:56:12
@@ -32,7 +50,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a::A(()) = a;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:57:12
@@ -41,7 +65,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a::A(_) = a;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:58:18
@@ -50,7 +80,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     match a { a::A(()) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:59:18
@@ -59,7 +95,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     match a { a::A(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:61:12
@@ -68,7 +110,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let a::B(_) = b;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:62:12
@@ -77,7 +125,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let a::B(_b) = b;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:63:18
@@ -86,7 +140,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:64:18
@@ -95,7 +155,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(_b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:18
@@ -104,7 +170,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:32
@@ -113,7 +185,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
-   |                                ^
+   |                                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:68:12
@@ -122,7 +200,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_, _) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:69:12
@@ -131,7 +215,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_a, _) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:70:12
@@ -140,7 +230,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_, _b) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:71:12
@@ -149,7 +245,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_a, _b) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:72:18
@@ -158,7 +260,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_, _) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:73:18
@@ -167,7 +275,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_a, _) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:74:18
@@ -176,7 +290,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_, _b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:75:18
@@ -185,7 +305,13 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_a, _b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:83:17
@@ -194,7 +320,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a2 = a::A;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:84:17
@@ -203,7 +335,13 @@
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let b2 = a::B;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:85:17
@@ -212,271 +350,421 @@
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let c2 = a::C;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:90:20
    |
 LL |     let a = other::A(());
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:91:20
    |
 LL |     let b = other::B(2);
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:92:20
    |
 LL |     let c = other::C(2, 3);
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:95:16
    |
 LL |     let other::A(()) = a;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:96:16
    |
 LL |     let other::A(_) = a;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:97:22
    |
 LL |     match a { other::A(()) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:98:22
    |
 LL |     match a { other::A(_) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:100:16
    |
 LL |     let other::B(_) = b;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:101:16
    |
 LL |     let other::B(_b) = b;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:102:22
    |
 LL |     match b { other::B(_) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:103:22
    |
 LL |     match b { other::B(_b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:104:22
    |
 LL |     match b { other::B(1) => {}
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:105:16
    |
 LL |         other::B(_) => {} }
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:107:16
    |
 LL |     let other::C(_, _) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:108:16
    |
 LL |     let other::C(_a, _) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:109:16
    |
 LL |     let other::C(_, _b) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:110:16
    |
 LL |     let other::C(_a, _b) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:111:22
    |
 LL |     match c { other::C(_, _) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:112:22
    |
 LL |     match c { other::C(_a, _) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:113:22
    |
 LL |     match c { other::C(_, _b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:114:22
    |
 LL |     match c { other::C(_a, _b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:122:21
    |
 LL |     let a2 = other::A;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:123:21
    |
 LL |     let b2 = other::B;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:124:21
    |
 LL |     let c2 = other::C;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 48 previous errors
 
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index 3c42f24..ad1052a 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -17,6 +17,8 @@
         //~^ WARN private trait `m::PrivTr` in public interface
         //~| WARN this was previously accepted
         //~| WARN private type `m::Priv` in public interface
+        //~| WARN private type `m::Priv` in public interface
+        //~| WARN this was previously accepted
         //~| WARN this was previously accepted
         type Alias1: PrivTr;
         type Alias2: PubTrAux1<Priv> = u8;
@@ -34,6 +36,7 @@
 
         type Exist = impl PrivTr;
         //~^ ERROR private trait `m::PrivTr` in public interface
+        //~| ERROR private trait `m::PrivTr` in public interface
         fn infer_exist() -> Self::Exist { Priv }
     }
 }
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 158862f..3cc551c 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -29,8 +29,23 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
+warning: private type `m::Priv` in public interface (error E0446)
+  --> $DIR/private-in-public-assoc-ty.rs:16:5
+   |
+LL | /     pub trait PubTr {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         fn infer_exist() -> Self::Exist;
+LL | |     }
+   | |_____^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:25:9
+  --> $DIR/private-in-public-assoc-ty.rs:27:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -39,7 +54,7 @@
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:32:9
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -48,7 +63,7 @@
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:35:9
+  --> $DIR/private-in-public-assoc-ty.rs:37:9
    |
 LL |     trait PrivTr {}
    |     - `m::PrivTr` declared as private
@@ -56,7 +71,16 @@
 LL |         type Exist = impl PrivTr;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error: aborting due to 3 previous errors
+error[E0445]: private trait `m::PrivTr` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:37:9
+   |
+LL |     trait PrivTr {}
+   |     - `m::PrivTr` declared as private
+...
+LL |         type Exist = impl PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0445, E0446.
 For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/privacy/private-item-simple.stderr b/src/test/ui/privacy/private-item-simple.stderr
index 0d5435e..f51b74f 100644
--- a/src/test/ui/privacy/private-item-simple.stderr
+++ b/src/test/ui/privacy/private-item-simple.stderr
@@ -2,7 +2,13 @@
   --> $DIR/private-item-simple.rs:6:8
    |
 LL |     a::f();
-   |        ^
+   |        ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/private-item-simple.rs:2:5
+   |
+LL |     fn f() {}
+   |     ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr
index e6a61fb..aac444b 100644
--- a/src/test/ui/privacy/restricted/test.stderr
+++ b/src/test/ui/privacy/restricted/test.stderr
@@ -26,13 +26,25 @@
   --> $DIR/test.rs:38:25
    |
 LL |     use pub_restricted::Crate;
-   |                         ^^^^^
+   |                         ^^^^^ this struct is private
+   |
+note: the struct `Crate` is defined here
+  --> $DIR/auxiliary/pub_restricted.rs:3:1
+   |
+LL | pub(crate) struct Crate;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: function `f` is private
   --> $DIR/test.rs:30:19
    |
 LL |     use foo::bar::f;
-   |                   ^
+   |                   ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/test.rs:8:9
+   |
+LL |         pub(super) fn f() {}
+   |         ^^^^^^^^^^^^^^^^^
 
 error[E0616]: field `x` of struct `foo::bar::S` is private
   --> $DIR/test.rs:31:5
diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs
index a01b8f3..50f04b1 100644
--- a/src/test/ui/proc-macro/disappearing-resolution.rs
+++ b/src/test/ui/proc-macro/disappearing-resolution.rs
@@ -8,7 +8,7 @@
 mod m {
     use test_macros::Empty;
 }
-use m::Empty; //~ ERROR derive macro `Empty` is private
+use m::Empty; //~ ERROR derive macro import `Empty` is private
 
 // To resolve `empty_helper` we need to resolve `Empty`.
 // During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`,
diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr
index a3377ef..3beaedf 100644
--- a/src/test/ui/proc-macro/disappearing-resolution.stderr
+++ b/src/test/ui/proc-macro/disappearing-resolution.stderr
@@ -4,11 +4,17 @@
 LL | #[empty_helper]
    |   ^^^^^^^^^^^^
 
-error[E0603]: derive macro `Empty` is private
+error[E0603]: derive macro import `Empty` is private
   --> $DIR/disappearing-resolution.rs:11:8
    |
 LL | use m::Empty;
-   |        ^^^^^
+   |        ^^^^^ this derive macro import is private
+   |
+note: the derive macro import `Empty` is defined here
+  --> $DIR/disappearing-resolution.rs:9:9
+   |
+LL |     use test_macros::Empty;
+   |         ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/proc-macro/issue-50493.rs b/src/test/ui/proc-macro/issue-50493.rs
index 5d1a9f2..f1934f6 100644
--- a/src/test/ui/proc-macro/issue-50493.rs
+++ b/src/test/ui/proc-macro/issue-50493.rs
@@ -4,6 +4,7 @@
 extern crate issue_50493;
 
 #[derive(Derive)] //~ ERROR field `field` of struct `Restricted` is private
+                  //~| ERROR field `field` of struct `Restricted` is private
 struct Restricted {
     pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules
 }
diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr
index 6b87244..56c7800 100644
--- a/src/test/ui/proc-macro/issue-50493.stderr
+++ b/src/test/ui/proc-macro/issue-50493.stderr
@@ -1,5 +1,5 @@
 error[E0742]: visibilities can only be restricted to ancestor modules
-  --> $DIR/issue-50493.rs:8:12
+  --> $DIR/issue-50493.rs:9:12
    |
 LL |     pub(in restricted) field: usize,
    |            ^^^^^^^^^^
@@ -10,7 +10,13 @@
 LL | #[derive(Derive)]
    |          ^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0616]: field `field` of struct `Restricted` is private
+  --> $DIR/issue-50493.rs:6:10
+   |
+LL | #[derive(Derive)]
+   |          ^^^^^^
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0616, E0742.
 For more information about an error, try `rustc --explain E0616`.
diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr
index e801c26..01eadbe 100644
--- a/src/test/ui/proc-macro/item-error.stderr
+++ b/src/test/ui/proc-macro/item-error.stderr
@@ -2,7 +2,13 @@
   --> $DIR/item-error.rs:10:8
    |
 LL |     a: &u64
-   |        ^ expected lifetime parameter
+   |        ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct A<'lifetime> {
+LL |     a: &'lifetime u64
+   |
 
 error: aborting due to previous error
 
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 b17c056..470b22b 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -46,6 +46,7 @@
 fn check_attr3() {}
 
 #[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope
+                    //~| ERROR cannot find derive macro `my_macro` in this scope
 #[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines
                            //~| ERROR expected derive macro, found macro `crate::my_macro`
 struct CheckDerive1;
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 c011a70..a617319 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -47,19 +47,19 @@
    |   ^^^^^^^ not an attribute
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:52:10
+  --> $DIR/macro-namespace-reserved-2.rs:53:10
    |
 LL | #[derive(my_macro_attr)]
    |          ^^^^^^^^^^^^^
 
 error: expected derive macro, found attribute macro `my_macro_attr`
-  --> $DIR/macro-namespace-reserved-2.rs:52:10
+  --> $DIR/macro-namespace-reserved-2.rs:53:10
    |
 LL | #[derive(my_macro_attr)]
    |          ^^^^^^^^^^^^^ not a derive macro
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:55:10
+  --> $DIR/macro-namespace-reserved-2.rs:56:10
    |
 LL | #[derive(MyTrait)]
    |          ^^^^^^^
@@ -77,13 +77,13 @@
    |   ^^^^^^^^^^^^^^^ not an attribute
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:49:10
+  --> $DIR/macro-namespace-reserved-2.rs:50:10
    |
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^
 
 error: expected derive macro, found macro `crate::my_macro`
-  --> $DIR/macro-namespace-reserved-2.rs:49:10
+  --> $DIR/macro-namespace-reserved-2.rs:50:10
    |
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^ not a derive macro
@@ -112,5 +112,11 @@
 LL | #[derive(my_macro)]
    |          ^^^^^^^^
 
-error: aborting due to 19 previous errors
+error: cannot find derive macro `my_macro` in this scope
+  --> $DIR/macro-namespace-reserved-2.rs:48:10
+   |
+LL | #[derive(my_macro)]
+   |          ^^^^^^^^
+
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs
index 7b2ffef..95a3f96 100644
--- a/src/test/ui/proc-macro/parent-source-spans.rs
+++ b/src/test/ui/proc-macro/parent-source-spans.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 // aux-build:parent-source-spans.rs
 #![feature(decl_macro, proc_macro_hygiene)]
 
diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr
index 3e54a71..9f0fefc 100644
--- a/src/test/ui/proc-macro/parent-source-spans.stderr
+++ b/src/test/ui/proc-macro/parent-source-spans.stderr
@@ -1,5 +1,5 @@
 error: first final: "hello"
-  --> $DIR/parent-source-spans.rs:15:12
+  --> $DIR/parent-source-spans.rs:19:12
    |
 LL |     three!($a, $b);
    |            ^^
@@ -8,7 +8,7 @@
    |     ----------------------- in this macro invocation
 
 error: second final: "world"
-  --> $DIR/parent-source-spans.rs:15:16
+  --> $DIR/parent-source-spans.rs:19:16
    |
 LL |     three!($a, $b);
    |                ^^
@@ -17,7 +17,7 @@
    |     ----------------------- in this macro invocation
 
 error: first parent: "hello"
-  --> $DIR/parent-source-spans.rs:9:5
+  --> $DIR/parent-source-spans.rs:13:5
    |
 LL |     two!($a, $b);
    |     ^^^^^^^^^^^^^
@@ -26,7 +26,7 @@
    |     ----------------------- in this macro invocation
 
 error: second parent: "world"
-  --> $DIR/parent-source-spans.rs:9:5
+  --> $DIR/parent-source-spans.rs:13:5
    |
 LL |     two!($a, $b);
    |     ^^^^^^^^^^^^^
@@ -35,31 +35,31 @@
    |     ----------------------- in this macro invocation
 
 error: first grandparent: "hello"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: second grandparent: "world"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: first source: "hello"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: second source: "world"
-  --> $DIR/parent-source-spans.rs:35:5
+  --> $DIR/parent-source-spans.rs:39:5
    |
 LL |     one!("hello", "world");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: first final: "yay"
-  --> $DIR/parent-source-spans.rs:15:12
+  --> $DIR/parent-source-spans.rs:19:12
    |
 LL |     three!($a, $b);
    |            ^^
@@ -68,7 +68,7 @@
    |     -------------------- in this macro invocation
 
 error: second final: "rust"
-  --> $DIR/parent-source-spans.rs:15:16
+  --> $DIR/parent-source-spans.rs:19:16
    |
 LL |     three!($a, $b);
    |                ^^
@@ -77,79 +77,94 @@
    |     -------------------- in this macro invocation
 
 error: first parent: "yay"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: second parent: "rust"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: first source: "yay"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: second source: "rust"
-  --> $DIR/parent-source-spans.rs:41:5
+  --> $DIR/parent-source-spans.rs:45:5
    |
 LL |     two!("yay", "rust");
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: first final: "hip"
-  --> $DIR/parent-source-spans.rs:47:12
+  --> $DIR/parent-source-spans.rs:51:12
    |
 LL |     three!("hip", "hop");
    |            ^^^^^
 
 error: second final: "hop"
-  --> $DIR/parent-source-spans.rs:47:19
+  --> $DIR/parent-source-spans.rs:51:19
    |
 LL |     three!("hip", "hop");
    |                   ^^^^^
 
 error: first source: "hip"
-  --> $DIR/parent-source-spans.rs:47:12
+  --> $DIR/parent-source-spans.rs:51:12
    |
 LL |     three!("hip", "hop");
    |            ^^^^^
 
 error: second source: "hop"
-  --> $DIR/parent-source-spans.rs:47:19
+  --> $DIR/parent-source-spans.rs:51:19
    |
 LL |     three!("hip", "hop");
    |                   ^^^^^
 
 error[E0425]: cannot find value `ok` in this scope
-  --> $DIR/parent-source-spans.rs:28:5
+  --> $DIR/parent-source-spans.rs:32:5
    |
 LL |     parent_source_spans!($($tokens)*);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     one!("hello", "world");
    |     ----------------------- in this macro invocation
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+   |     --------------------------------------------------- similarly named tuple variant `Ok` defined here
 
 error[E0425]: cannot find value `ok` in this scope
-  --> $DIR/parent-source-spans.rs:28:5
+  --> $DIR/parent-source-spans.rs:32:5
    |
 LL |     parent_source_spans!($($tokens)*);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     two!("yay", "rust");
    |     -------------------- in this macro invocation
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+   |     --------------------------------------------------- similarly named tuple variant `Ok` defined here
 
 error[E0425]: cannot find value `ok` in this scope
-  --> $DIR/parent-source-spans.rs:28:5
+  --> $DIR/parent-source-spans.rs:32:5
    |
 LL |     parent_source_spans!($($tokens)*);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     three!("hip", "hop");
    |     --------------------- in this macro invocation
+   | 
+  ::: $SRC_DIR/libcore/result.rs:LL:COL
+   |
+LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+   |     --------------------------------------------------- similarly named tuple variant `Ok` defined here
 
 error: aborting due to 21 previous errors
 
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
index d2282af..8ff36ff 100644
--- a/src/test/ui/proc-macro/resolve-error.rs
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 // aux-build:derive-foo.rs
 // aux-build:derive-clona.rs
 // aux-build:test-macros.rs
@@ -21,6 +25,7 @@
 
 #[derive(FooWithLongNan)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct Foo;
 
 // Interpreted as an unstable custom attribute
@@ -33,14 +38,17 @@
 
 #[derive(Dlone)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct A;
 
 #[derive(Dlona)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct B;
 
 #[derive(attr_proc_macra)]
 //~^ ERROR cannot find
+//~| ERROR cannot find
 struct C;
 
 fn main() {
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
index 02c82c0..73a6ab1 100644
--- a/src/test/ui/proc-macro/resolve-error.stderr
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -1,17 +1,22 @@
 error: cannot find macro `bang_proc_macrp` in this scope
-  --> $DIR/resolve-error.rs:56:5
+  --> $DIR/resolve-error.rs:64:5
    |
 LL |     bang_proc_macrp!();
    |     ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
+   | 
+  ::: $DIR/auxiliary/test-macros.rs:15:1
+   |
+LL | pub fn empty(_: TokenStream) -> TokenStream {
+   | ------------------------------------------- similarly named macro `bang_proc_macro` defined here
 
 error: cannot find macro `Dlona` in this scope
-  --> $DIR/resolve-error.rs:53:5
+  --> $DIR/resolve-error.rs:61:5
    |
 LL |     Dlona!();
    |     ^^^^^
 
 error: cannot find macro `attr_proc_macra` in this scope
-  --> $DIR/resolve-error.rs:50:5
+  --> $DIR/resolve-error.rs:58:5
    |
 LL | / macro_rules! attr_proc_mac {
 LL | |     () => {}
@@ -22,7 +27,7 @@
    |       ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
 
 error: cannot find macro `FooWithLongNama` in this scope
-  --> $DIR/resolve-error.rs:47:5
+  --> $DIR/resolve-error.rs:55:5
    |
 LL | / macro_rules! FooWithLongNam {
 LL | |     () => {}
@@ -33,40 +38,99 @@
    |       ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam`
 
 error: cannot find derive macro `attr_proc_macra` in this scope
-  --> $DIR/resolve-error.rs:42:10
+  --> $DIR/resolve-error.rs:49:10
+   |
+LL | #[derive(attr_proc_macra)]
+   |          ^^^^^^^^^^^^^^^
+
+error: cannot find derive macro `attr_proc_macra` in this scope
+  --> $DIR/resolve-error.rs:49:10
    |
 LL | #[derive(attr_proc_macra)]
    |          ^^^^^^^^^^^^^^^
 
 error: cannot find derive macro `Dlona` in this scope
-  --> $DIR/resolve-error.rs:38:10
+  --> $DIR/resolve-error.rs:44:10
    |
 LL | #[derive(Dlona)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clona`
+   | 
+  ::: $DIR/auxiliary/derive-clona.rs:11:1
+   |
+LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
+   | ------------------------------------------------------- similarly named derive macro `Clona` defined here
+
+error: cannot find derive macro `Dlona` in this scope
+  --> $DIR/resolve-error.rs:44:10
+   |
+LL | #[derive(Dlona)]
+   |          ^^^^^ help: a derive macro with a similar name exists: `Clona`
+   | 
+  ::: $DIR/auxiliary/derive-clona.rs:11:1
+   |
+LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
+   | ------------------------------------------------------- similarly named derive macro `Clona` defined here
 
 error: cannot find derive macro `Dlone` in this scope
-  --> $DIR/resolve-error.rs:34:10
+  --> $DIR/resolve-error.rs:39:10
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+   | 
+  ::: $SRC_DIR/libcore/clone.rs:LL:COL
+   |
+LL | pub macro Clone($item:item) {
+   | --------------------------- similarly named derive macro `Clone` defined here
+
+error: cannot find derive macro `Dlone` in this scope
+  --> $DIR/resolve-error.rs:39:10
+   |
+LL | #[derive(Dlone)]
+   |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+   | 
+  ::: $SRC_DIR/libcore/clone.rs:LL:COL
+   |
+LL | pub macro Clone($item:item) {
+   | --------------------------- similarly named derive macro `Clone` defined here
 
 error: cannot find attribute `FooWithLongNan` in this scope
-  --> $DIR/resolve-error.rs:31:3
+  --> $DIR/resolve-error.rs:36:3
    |
 LL | #[FooWithLongNan]
    |   ^^^^^^^^^^^^^^
 
 error: cannot find attribute `attr_proc_macra` in this scope
-  --> $DIR/resolve-error.rs:27:3
+  --> $DIR/resolve-error.rs:32:3
    |
 LL | #[attr_proc_macra]
    |   ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro`
+   | 
+  ::: $DIR/auxiliary/test-macros.rs:20:1
+   |
+LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+   | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here
 
 error: cannot find derive macro `FooWithLongNan` in this scope
-  --> $DIR/resolve-error.rs:22:10
+  --> $DIR/resolve-error.rs:26:10
    |
 LL | #[derive(FooWithLongNan)]
    |          ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
+   | 
+  ::: $DIR/auxiliary/derive-foo.rs:11:1
+   |
+LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
+   | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
 
-error: aborting due to 10 previous errors
+error: cannot find derive macro `FooWithLongNan` in this scope
+  --> $DIR/resolve-error.rs:26:10
+   |
+LL | #[derive(FooWithLongNan)]
+   |          ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
+   | 
+  ::: $DIR/auxiliary/derive-foo.rs:11:1
+   |
+LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
+   | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
+
+error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/range/range_traits-1.rs b/src/test/ui/range/range_traits-1.rs
index e28e474..4f57c32 100644
--- a/src/test/ui/range/range_traits-1.rs
+++ b/src/test/ui/range/range_traits-1.rs
@@ -4,21 +4,45 @@
 struct AllTheRanges {
     a: Range<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     b: RangeTo<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     c: RangeFrom<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     d: RangeFull,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     e: RangeInclusive<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
     f: RangeToInclusive<usize>,
     //~^ ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
+    //~| ERROR can't compare
     //~| ERROR Ord
 }
 
diff --git a/src/test/ui/range/range_traits-1.stderr b/src/test/ui/range/range_traits-1.stderr
index d085cab..f60ec23 100644
--- a/src/test/ui/range/range_traits-1.stderr
+++ b/src/test/ui/range/range_traits-1.stderr
@@ -8,7 +8,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
-  --> $DIR/range_traits-1.rs:8:5
+  --> $DIR/range_traits-1.rs:12:5
    |
 LL |     b: RangeTo<usize>,
    |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
@@ -17,7 +17,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
-  --> $DIR/range_traits-1.rs:11:5
+  --> $DIR/range_traits-1.rs:19:5
    |
 LL |     c: RangeFrom<usize>,
    |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
@@ -26,7 +26,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
-  --> $DIR/range_traits-1.rs:14:5
+  --> $DIR/range_traits-1.rs:26:5
    |
 LL |     d: RangeFull,
    |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
@@ -35,7 +35,7 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
-  --> $DIR/range_traits-1.rs:17:5
+  --> $DIR/range_traits-1.rs:33:5
    |
 LL |     e: RangeInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
@@ -44,7 +44,223 @@
    = note: required by `std::cmp::PartialOrd::partial_cmp`
 
 error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
-  --> $DIR/range_traits-1.rs:20:5
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
+   |
+LL |     f: RangeToInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::Range<usize>` with `std::ops::Range<usize>`
+  --> $DIR/range_traits-1.rs:5:5
+   |
+LL |     a: Range<usize>,
+   |     ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::Range<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>`
+  --> $DIR/range_traits-1.rs:12:5
+   |
+LL |     b: RangeTo<usize>,
+   |     ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeTo<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>`
+  --> $DIR/range_traits-1.rs:19:5
+   |
+LL |     c: RangeFrom<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFrom<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull`
+  --> $DIR/range_traits-1.rs:26:5
+   |
+LL |     d: RangeFull,
+   |     ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeFull`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>`
+  --> $DIR/range_traits-1.rs:33:5
+   |
+LL |     e: RangeInclusive<usize>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>`
+   |
+   = help: the trait `std::cmp::PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>`
+   = note: required by `std::cmp::PartialOrd::partial_cmp`
+
+error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>`
+  --> $DIR/range_traits-1.rs:40:5
    |
 LL |     f: RangeToInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>`
@@ -61,7 +277,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeTo<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:8:5
+  --> $DIR/range_traits-1.rs:12:5
    |
 LL |     b: RangeTo<usize>,
    |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeTo<usize>`
@@ -69,7 +285,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeFrom<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:11:5
+  --> $DIR/range_traits-1.rs:19:5
    |
 LL |     c: RangeFrom<usize>,
    |     ^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeFrom<usize>`
@@ -77,7 +293,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeFull: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:14:5
+  --> $DIR/range_traits-1.rs:26:5
    |
 LL |     d: RangeFull,
    |     ^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeFull`
@@ -85,7 +301,7 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeInclusive<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:17:5
+  --> $DIR/range_traits-1.rs:33:5
    |
 LL |     e: RangeInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeInclusive<usize>`
@@ -93,13 +309,13 @@
    = note: required by `std::cmp::Ord::cmp`
 
 error[E0277]: the trait bound `std::ops::RangeToInclusive<usize>: std::cmp::Ord` is not satisfied
-  --> $DIR/range_traits-1.rs:20:5
+  --> $DIR/range_traits-1.rs:40:5
    |
 LL |     f: RangeToInclusive<usize>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `std::ops::RangeToInclusive<usize>`
    |
    = note: required by `std::cmp::Ord::cmp`
 
-error: aborting due to 12 previous errors
+error: aborting due to 36 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/reachable/unreachable-variant.stderr b/src/test/ui/reachable/unreachable-variant.stderr
index 276c77f..c2e1d77 100644
--- a/src/test/ui/reachable/unreachable-variant.stderr
+++ b/src/test/ui/reachable/unreachable-variant.stderr
@@ -2,7 +2,13 @@
   --> $DIR/unreachable-variant.rs:6:21
    |
 LL |     let _x = other::super_sekrit::sooper_sekrit::baz;
-   |                     ^^^^^^^^^^^^
+   |                     ^^^^^^^^^^^^ this module is private
+   |
+note: the module `super_sekrit` is defined here
+  --> $DIR/auxiliary/unreachable_variant.rs:1:1
+   |
+LL | mod super_sekrit {
+   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26548.rs b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
similarity index 100%
rename from src/test/ui/issues/issue-26548.rs
rename to src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
diff --git a/src/test/ui/issues/issue-26548.stderr b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
similarity index 87%
rename from src/test/ui/issues/issue-26548.stderr
rename to src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
index 3c21367..6a83f91 100644
--- a/src/test/ui/issues/issue-26548.stderr
+++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
@@ -3,7 +3,7 @@
    = note: ...which requires computing layout of `S`...
    = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
 note: cycle used when processing `main`
-  --> $DIR/issue-26548.rs:11:1
+  --> $DIR/issue-26548-recursion-via-normalize.rs:11:1
    |
 LL | fn main() {
    | ^^^^^^^^^
diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
new file mode 100644
index 0000000..d9996b8
--- /dev/null
+++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
@@ -0,0 +1,17 @@
+// Dropck shouldn't hit a recursion limit from checking `S<u32>` since it has
+// no free regions or type parameters.
+// Codegen however, has to error for the infinitely many `drop_in_place`
+// functions it has been asked to create.
+// build-fail
+
+struct S<T> {
+    t: T,
+    s: Box<S<fn(u: T)>>,
+}
+
+fn f(x: S<u32>) {}
+
+fn main() {
+    // Force instantiation.
+    f as fn(_);
+}
diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
new file mode 100644
index 0000000..de6df4c
--- /dev/null
+++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
@@ -0,0 +1,4 @@
+error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.rs b/src/test/ui/regions/regions-close-object-into-object-5.rs
index 609c8ce..2921a2b 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.rs
+++ b/src/test/ui/regions/regions-close-object-into-object-5.rs
@@ -21,6 +21,7 @@
         //~| ERROR the parameter type `T` may not live long enough
         //~| ERROR the parameter type `T` may not live long enough
         //~| ERROR the parameter type `T` may not live long enough
+        //~| ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
index 01975d4..7c530ce 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -88,6 +88,21 @@
 LL |     box B(&*v) as Box<X>
    |           ^^^
 
-error: aborting due to 6 previous errors
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/regions-close-object-into-object-5.rs:17:11
+   |
+LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+LL |     // oh dear!
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+   |
+note: ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
+  --> $DIR/regions-close-object-into-object-5.rs:17:11
+   |
+LL |     box B(&*v) as Box<X>
+   |           ^^^
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/regions/regions-in-enums-anon.stderr b/src/test/ui/regions/regions-in-enums-anon.stderr
index ae06e76..41655a2 100644
--- a/src/test/ui/regions/regions-in-enums-anon.stderr
+++ b/src/test/ui/regions/regions-in-enums-anon.stderr
@@ -2,7 +2,13 @@
   --> $DIR/regions-in-enums-anon.rs:4:9
    |
 LL |     Bar(&isize)
-   |         ^ expected lifetime parameter
+   |         ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | enum Foo<'lifetime> {
+LL |     Bar(&'lifetime isize)
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-in-enums.stderr b/src/test/ui/regions/regions-in-enums.stderr
index cfed9fe..6653765 100644
--- a/src/test/ui/regions/regions-in-enums.stderr
+++ b/src/test/ui/regions/regions-in-enums.stderr
@@ -1,12 +1,16 @@
 error[E0261]: use of undeclared lifetime name `'foo`
   --> $DIR/regions-in-enums.rs:13:9
    |
+LL | enum No0 {
+   |         - help: consider introducing lifetime `'foo` here: `<'foo>`
 LL |     X5(&'foo usize)
    |         ^^^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-in-enums.rs:17:9
    |
+LL | enum No1 {
+   |         - help: consider introducing lifetime `'a` here: `<'a>`
 LL |     X6(&'a usize)
    |         ^^ undeclared lifetime
 
diff --git a/src/test/ui/regions/regions-in-structs-anon.stderr b/src/test/ui/regions/regions-in-structs-anon.stderr
index a1d4ebb..fbe8036 100644
--- a/src/test/ui/regions/regions-in-structs-anon.stderr
+++ b/src/test/ui/regions/regions-in-structs-anon.stderr
@@ -2,7 +2,13 @@
   --> $DIR/regions-in-structs-anon.rs:4:8
    |
 LL |     x: &isize
-   |        ^ expected lifetime parameter
+   |        ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Foo<'lifetime> {
+LL |     x: &'lifetime isize
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-in-structs.stderr b/src/test/ui/regions/regions-in-structs.stderr
index 8314942..5dfdc2e 100644
--- a/src/test/ui/regions/regions-in-structs.stderr
+++ b/src/test/ui/regions/regions-in-structs.stderr
@@ -1,12 +1,17 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-in-structs.rs:10:9
    |
+LL | struct StructDecl {
+   |                  - help: consider introducing lifetime `'a` here: `<'a>`
 LL |     a: &'a isize,
    |         ^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-in-structs.rs:11:9
    |
+LL | struct StructDecl {
+   |                  - help: consider introducing lifetime `'a` here: `<'a>`
+LL |     a: &'a isize,
 LL |     b: &'a isize,
    |         ^^ undeclared lifetime
 
diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr
index 5f6a48a..79ebef4 100644
--- a/src/test/ui/regions/regions-name-undeclared.stderr
+++ b/src/test/ui/regions/regions-name-undeclared.stderr
@@ -3,34 +3,67 @@
    |
 LL |     fn m4(&self, arg: &'b isize) { }
    |                        ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> Foo<'a> {
+   |      ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn m4<'b>(&self, arg: &'b isize) { }
+   |          ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:16:12
    |
 LL |     fn m5(&'b self) { }
    |            ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> Foo<'a> {
+   |      ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn m5<'b>(&'b self) { }
+   |          ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:17:27
    |
 LL |     fn m6(&self, arg: Foo<'b>) { }
    |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b, 'a> Foo<'a> {
+   |      ^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn m6<'b>(&self, arg: Foo<'b>) { }
+   |          ^^^^
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:25:22
    |
 LL |     type X = Option<&'a isize>;
-   |                      ^^ undeclared lifetime
+   |           -          ^^ undeclared lifetime
+   |           |
+   |           help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:27:13
    |
+LL |     enum E {
+   |           - help: consider introducing lifetime `'a` here: `<'a>`
 LL |         E1(&'a isize)
    |             ^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:30:13
    |
+LL |     struct S {
+   |             - help: consider introducing lifetime `'a` here: `<'a>`
 LL |         f: &'a isize
    |             ^^ undeclared lifetime
 
@@ -38,13 +71,17 @@
   --> $DIR/regions-name-undeclared.rs:32:14
    |
 LL |     fn f(a: &'a isize) { }
-   |              ^^ undeclared lifetime
+   |         -    ^^ undeclared lifetime
+   |         |
+   |         help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:40:17
    |
 LL | fn fn_types(a: &'a isize,
-   |                 ^^ undeclared lifetime
+   |            -    ^^ undeclared lifetime
+   |            |
+   |            help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:42:36
@@ -61,6 +98,9 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:46:17
    |
+LL | fn fn_types(a: &'a isize,
+   |            - help: consider introducing lifetime `'a` here: `<'a>`
+...
 LL |             c: &'a isize)
    |                 ^^ undeclared lifetime
 
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
index e94e8b2..e912805 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
@@ -20,6 +20,8 @@
 
 // Here we get an error: we need `'a: 'b`.
 fn bar<'a, 'b>() //~ ERROR cannot infer
+                 //~| ERROR cannot infer
+                 //~| ERROR cannot infer
     where <() as Project<'a, 'b>>::Item : Eq
 {
 }
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index 8a600d2..cc2245f 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -2,6 +2,8 @@
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
    |
 LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
 LL | | {
 LL | | }
@@ -21,6 +23,8 @@
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
    |
 LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
 LL | | {
 LL | | }
@@ -28,6 +32,74 @@
    = note: expected  `Project<'a, 'b>`
               found  `Project<'_, '_>`
 
-error: aborting due to previous error
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+   |
+LL | fn bar<'a, 'b>()
+   |        ^^
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+   |
+LL | fn bar<'a, 'b>()
+   |            ^^
+note: ...so that the types are compatible
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   = note: expected  `Project<'a, 'b>`
+              found  `Project<'_, '_>`
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+   |
+LL | fn bar<'a, 'b>()
+   |        ^^
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+   |
+LL | fn bar<'a, 'b>()
+   |            ^^
+note: ...so that the types are compatible
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |
+LL | |
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   = note: expected  `Project<'a, 'b>`
+              found  `Project<'_, '_>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-undeclared.stderr b/src/test/ui/regions/regions-undeclared.stderr
index 495aec3..6bfde55 100644
--- a/src/test/ui/regions/regions-undeclared.stderr
+++ b/src/test/ui/regions/regions-undeclared.stderr
@@ -7,12 +7,17 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-undeclared.rs:4:10
    |
+LL | enum EnumDecl {
+   |              - help: consider introducing lifetime `'a` here: `<'a>`
 LL |     Foo(&'a isize),
    |          ^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-undeclared.rs:5:10
    |
+LL | enum EnumDecl {
+   |              - help: consider introducing lifetime `'a` here: `<'a>`
+LL |     Foo(&'a isize),
 LL |     Bar(&'a isize),
    |          ^^ undeclared lifetime
 
@@ -20,11 +25,15 @@
   --> $DIR/regions-undeclared.rs:8:15
    |
 LL | fn fnDecl(x: &'a isize,
-   |               ^^ undeclared lifetime
+   |          -    ^^ undeclared lifetime
+   |          |
+   |          help: consider introducing lifetime `'a` here: `<'a>`
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-undeclared.rs:9:15
    |
+LL | fn fnDecl(x: &'a isize,
+   |          - help: consider introducing lifetime `'a` here: `<'a>`
 LL |           y: &'a isize)
    |               ^^ undeclared lifetime
 
diff --git a/src/test/ui/repr/repr-align-assign.fixed b/src/test/ui/repr/repr-align-assign.fixed
index 2e1d9a2..59ca22e 100644
--- a/src/test/ui/repr/repr-align-assign.fixed
+++ b/src/test/ui/repr/repr-align-assign.fixed
@@ -3,9 +3,11 @@
 #![allow(dead_code)]
 
 #[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
+                 //~| ERROR incorrect `repr(align)` attribute format
 struct A(u64);
 
 #[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format
+                   //~| ERROR incorrect `repr(align)` attribute format
 struct B(u64);
 
 fn main() {}
diff --git a/src/test/ui/repr/repr-align-assign.rs b/src/test/ui/repr/repr-align-assign.rs
index b8f7c15..6b77992 100644
--- a/src/test/ui/repr/repr-align-assign.rs
+++ b/src/test/ui/repr/repr-align-assign.rs
@@ -3,9 +3,11 @@
 #![allow(dead_code)]
 
 #[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format
+                 //~| ERROR incorrect `repr(align)` attribute format
 struct A(u64);
 
 #[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format
+                   //~| ERROR incorrect `repr(align)` attribute format
 struct B(u64);
 
 fn main() {}
diff --git a/src/test/ui/repr/repr-align-assign.stderr b/src/test/ui/repr/repr-align-assign.stderr
index 177bd81..192312d 100644
--- a/src/test/ui/repr/repr-align-assign.stderr
+++ b/src/test/ui/repr/repr-align-assign.stderr
@@ -5,10 +5,22 @@
    |        ^^^^^^^ help: use parentheses instead: `align(8)`
 
 error[E0693]: incorrect `repr(align)` attribute format
-  --> $DIR/repr-align-assign.rs:8:8
+  --> $DIR/repr-align-assign.rs:9:8
    |
 LL | #[repr(align="8")]
    |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
 
-error: aborting due to 2 previous errors
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:5:8
+   |
+LL | #[repr(align=8)]
+   |        ^^^^^^^ help: use parentheses instead: `align(8)`
+
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:9:8
+   |
+LL | #[repr(align="8")]
+   |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/repr/repr-align.rs b/src/test/ui/repr/repr-align.rs
index bc6a9fe..58ecf9a 100644
--- a/src/test/ui/repr/repr-align.rs
+++ b/src/test/ui/repr/repr-align.rs
@@ -1,24 +1,30 @@
 #![allow(dead_code)]
 
 #[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+                     //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
 struct S0(i32);
 
 #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+                   //~| ERROR: invalid `repr(align)` attribute: not a power of two
 struct S1(i32);
 
 #[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+                           //~| ERROR: invalid `repr(align)` attribute: larger than 2^29
 struct S2(i32);
 
 #[repr(align(536870912))] // ok: this is the largest accepted alignment
 struct S3(i32);
 
 #[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
+                     //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
 enum E0 { A, B }
 
 #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
+                   //~| ERROR: invalid `repr(align)` attribute: not a power of two
 enum E1 { A, B }
 
 #[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
+                           //~| ERROR: invalid `repr(align)` attribute: larger than 2^29
 enum E2 { A, B }
 
 #[repr(align(536870912))] // ok: this is the largest accepted alignment
diff --git a/src/test/ui/repr/repr-align.stderr b/src/test/ui/repr/repr-align.stderr
index 280cab2..900a811 100644
--- a/src/test/ui/repr/repr-align.stderr
+++ b/src/test/ui/repr/repr-align.stderr
@@ -5,35 +5,71 @@
    |        ^^^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: not a power of two
-  --> $DIR/repr-align.rs:6:8
+  --> $DIR/repr-align.rs:7:8
    |
 LL | #[repr(align(15))]
    |        ^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: larger than 2^29
-  --> $DIR/repr-align.rs:9:8
+  --> $DIR/repr-align.rs:11:8
    |
 LL | #[repr(align(4294967296))]
    |        ^^^^^^^^^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
-  --> $DIR/repr-align.rs:15:8
+  --> $DIR/repr-align.rs:18:8
    |
 LL | #[repr(align(16.0))]
    |        ^^^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: not a power of two
-  --> $DIR/repr-align.rs:18:8
+  --> $DIR/repr-align.rs:22:8
    |
 LL | #[repr(align(15))]
    |        ^^^^^^^^^
 
 error[E0589]: invalid `repr(align)` attribute: larger than 2^29
-  --> $DIR/repr-align.rs:21:8
+  --> $DIR/repr-align.rs:26:8
    |
 LL | #[repr(align(4294967296))]
    |        ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+  --> $DIR/repr-align.rs:3:8
+   |
+LL | #[repr(align(16.0))]
+   |        ^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/repr-align.rs:7:8
+   |
+LL | #[repr(align(15))]
+   |        ^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+  --> $DIR/repr-align.rs:11:8
+   |
+LL | #[repr(align(4294967296))]
+   |        ^^^^^^^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
+  --> $DIR/repr-align.rs:18:8
+   |
+LL | #[repr(align(16.0))]
+   |        ^^^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/repr-align.rs:22:8
+   |
+LL | #[repr(align(15))]
+   |        ^^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: larger than 2^29
+  --> $DIR/repr-align.rs:26:8
+   |
+LL | #[repr(align(4294967296))]
+   |        ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0589`.
diff --git a/src/test/ui/repr/repr-packed-contains-align.rs b/src/test/ui/repr/repr-packed-contains-align.rs
index a361034..67d87eb 100644
--- a/src/test/ui/repr/repr-packed-contains-align.rs
+++ b/src/test/ui/repr/repr-packed-contains-align.rs
@@ -16,34 +16,34 @@
 }
 
 #[repr(packed)]
-struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SC(SA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SD(SB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SE(UA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SF(UB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UC { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     a: UA
 }
 
 #[repr(packed)]
-union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UD { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     n: UB
 }
 
 #[repr(packed)]
-union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UE { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     a: SA
 }
 
 #[repr(packed)]
-union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UF { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     n: SB
 }
 
diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr
index df001d6..32f9bb8 100644
--- a/src/test/ui/repr/repr-packed-contains-align.stderr
+++ b/src/test/ui/repr/repr-packed-contains-align.stderr
@@ -1,58 +1,154 @@
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:19:1
    |
 LL | struct SC(SA);
    | ^^^^^^^^^^^^^^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:22:1
    |
 LL | struct SD(SB);
    | ^^^^^^^^^^^^^^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
+note: `SD` contains a field of type `SB`
+  --> $DIR/repr-packed-contains-align.rs:22:11
+   |
+LL | struct SD(SB);
+   |           ^^
+note: ...which contains a field of type `SA`
+  --> $DIR/repr-packed-contains-align.rs:7:11
+   |
+LL | struct SB(SA);
+   |           ^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:25:1
    |
 LL | struct SE(UA);
    | ^^^^^^^^^^^^^^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:28:1
    |
 LL | struct SF(UB);
    | ^^^^^^^^^^^^^^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
+note: `SF` contains a field of type `UB`
+  --> $DIR/repr-packed-contains-align.rs:28:11
+   |
+LL | struct SF(UB);
+   |           ^^
+note: ...which contains a field of type `UA`
+  --> $DIR/repr-packed-contains-align.rs:15:5
+   |
+LL |     a: UA
+   |     ^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:31:1
    |
 LL | / union UC {
 LL | |     a: UA
 LL | | }
    | |_^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:36:1
    |
 LL | / union UD {
 LL | |     n: UB
 LL | | }
    | |_^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
+note: `UD` contains a field of type `UB`
+  --> $DIR/repr-packed-contains-align.rs:37:5
+   |
+LL |     n: UB
+   |     ^
+note: ...which contains a field of type `UA`
+  --> $DIR/repr-packed-contains-align.rs:15:5
+   |
+LL |     a: UA
+   |     ^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:41:1
    |
 LL | / union UE {
 LL | |     a: SA
 LL | | }
    | |_^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:46:1
    |
 LL | / union UF {
 LL | |     n: SB
 LL | | }
    | |_^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
+note: `UF` contains a field of type `SB`
+  --> $DIR/repr-packed-contains-align.rs:47:5
+   |
+LL |     n: SB
+   |     ^
+note: ...which contains a field of type `SA`
+  --> $DIR/repr-packed-contains-align.rs:7:11
+   |
+LL | struct SB(SA);
+   |           ^^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/resolve/impl-items-vis-unresolved.rs b/src/test/ui/resolve/impl-items-vis-unresolved.rs
index 9b4fe49..1494c1c 100644
--- a/src/test/ui/resolve/impl-items-vis-unresolved.rs
+++ b/src/test/ui/resolve/impl-items-vis-unresolved.rs
@@ -18,7 +18,8 @@
 pub struct RawFloatState;
 impl RawFloatState {
     perftools_inline! {
-        pub(super) fn new() {} //~ ERROR failed to resolve: there are too many initial `super`s
+        pub(super) fn new() {}
+        //~^ ERROR failed to resolve: there are too many leading `super` keywords
     }
 }
 
diff --git a/src/test/ui/resolve/impl-items-vis-unresolved.stderr b/src/test/ui/resolve/impl-items-vis-unresolved.stderr
index 8e285e5..f2293d2 100644
--- a/src/test/ui/resolve/impl-items-vis-unresolved.stderr
+++ b/src/test/ui/resolve/impl-items-vis-unresolved.stderr
@@ -1,8 +1,8 @@
-error[E0433]: failed to resolve: there are too many initial `super`s.
+error[E0433]: failed to resolve: there are too many leading `super` keywords
   --> $DIR/impl-items-vis-unresolved.rs:21:13
    |
 LL |         pub(super) fn new() {}
-   |             ^^^^^ there are too many initial `super`s.
+   |             ^^^^^ there are too many leading `super` keywords
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/levenshtein.rs b/src/test/ui/resolve/levenshtein.rs
index a6f4716..6a98782 100644
--- a/src/test/ui/resolve/levenshtein.rs
+++ b/src/test/ui/resolve/levenshtein.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 const MAX_ITEM: usize = 10;
 
 fn foo_bar() {}
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index 8d8f3f3..a622d6c 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -1,11 +1,11 @@
 error[E0412]: cannot find type `esize` in this scope
-  --> $DIR/levenshtein.rs:5:11
+  --> $DIR/levenshtein.rs:9:11
    |
 LL | fn foo(c: esize) {} // Misspelled primitive type name.
    |           ^^^^^ help: a builtin type with a similar name exists: `isize`
 
 error[E0412]: cannot find type `Baz` in this scope
-  --> $DIR/levenshtein.rs:10:10
+  --> $DIR/levenshtein.rs:14:10
    |
 LL | enum Bar { }
    | ------------ similarly named enum `Bar` defined here
@@ -14,19 +14,24 @@
    |          ^^^ help: an enum with a similar name exists: `Bar`
 
 error[E0412]: cannot find type `Opiton` in this scope
-  --> $DIR/levenshtein.rs:12:10
+  --> $DIR/levenshtein.rs:16:10
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
    |          ^^^^^^ help: an enum with a similar name exists: `Option`
+   | 
+  ::: $SRC_DIR/libcore/option.rs:LL:COL
+   |
+LL | pub enum Option<T> {
+   | ------------------ similarly named enum `Option` defined here
 
 error[E0412]: cannot find type `Baz` in this scope
-  --> $DIR/levenshtein.rs:16:14
+  --> $DIR/levenshtein.rs:20:14
    |
 LL |     type A = Baz; // No suggestion here, Bar is not visible
    |              ^^^ not found in this scope
 
 error[E0425]: cannot find value `MAXITEM` in this scope
-  --> $DIR/levenshtein.rs:24:20
+  --> $DIR/levenshtein.rs:28:20
    |
 LL | const MAX_ITEM: usize = 10;
    | --------------------------- similarly named constant `MAX_ITEM` defined here
@@ -35,7 +40,7 @@
    |                    ^^^^^^^ help: a constant with a similar name exists: `MAX_ITEM`
 
 error[E0425]: cannot find function `foobar` in this scope
-  --> $DIR/levenshtein.rs:26:5
+  --> $DIR/levenshtein.rs:30:5
    |
 LL | fn foo_bar() {}
    | --------------- similarly named function `foo_bar` defined here
@@ -44,7 +49,7 @@
    |     ^^^^^^ help: a function with a similar name exists: `foo_bar`
 
 error[E0412]: cannot find type `first` in module `m`
-  --> $DIR/levenshtein.rs:28:15
+  --> $DIR/levenshtein.rs:32:15
    |
 LL |     pub struct First;
    |     ----------------- similarly named struct `First` defined here
@@ -53,7 +58,7 @@
    |               ^^^^^ help: a struct with a similar name exists (notice the capitalization): `First`
 
 error[E0425]: cannot find value `second` in module `m`
-  --> $DIR/levenshtein.rs:28:26
+  --> $DIR/levenshtein.rs:32:26
    |
 LL |     pub struct Second;
    |     ------------------ similarly named unit struct `Second` defined here
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 688720e..08a1d79 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -253,25 +253,49 @@
   --> $DIR/privacy-enum-ctor.rs:57:22
    |
 LL |     let _: Z = m::n::Z;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:61:22
    |
 LL |     let _: Z = m::n::Z::Fn;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:64:22
    |
 LL |     let _: Z = m::n::Z::Struct;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:68:22
    |
 LL |     let _: Z = m::n::Z::Unit {};
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/privacy-enum-ctor.rs:27:20
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index f1a1de4..1673ec4 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -45,7 +45,13 @@
    |                            --------------- a constructor is private if any of the fields is private
 ...
 LL |         n::Z;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/privacy-struct-ctor.rs:12:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:29:8
@@ -54,7 +60,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     m::S;
-   |        ^
+   |        ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/privacy-struct-ctor.rs:6:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:31:19
@@ -63,7 +75,13 @@
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let _: S = m::S(2);
-   |                   ^
+   |                   ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/privacy-struct-ctor.rs:6:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:35:11
@@ -72,29 +90,47 @@
    |                            --------------- a constructor is private if any of the fields is private
 ...
 LL |     m::n::Z;
-   |           ^
+   |           ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/privacy-struct-ctor.rs:12:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:41:16
    |
 LL |     xcrate::m::S;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18
    |
 LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/auxiliary/privacy-struct-ctor.rs:2:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:45:19
    |
 LL |     xcrate::m::n::Z;
-   |                   ^
+   |                   ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28
    |
 LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/auxiliary/privacy-struct-ctor.rs:5:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfc-2005-default-binding-mode/slice.rs
index 1484b8c..363a0e3 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/slice.rs
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 pub fn main() {
     let sl: &[u8] = b"foo";
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
index f1e91a0..c234fdf 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/slice.rs:6:11
+  --> $DIR/slice.rs:4:11
    |
 LL |     match sl {
    |           ^^ pattern `&[]` not covered
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
index 944965a..f992988 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -14,18 +14,30 @@
   --> $DIR/struct.rs:23:32
    |
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
-   |                                ^^^^^^^^^^^
+   |                                ^^^^^^^^^^^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/structs.rs:11:24
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    |                        ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `TupleStruct` is defined here
+  --> $DIR/auxiliary/structs.rs:11:1
+   |
+LL | pub struct TupleStruct(pub u16, pub u16);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: unit struct `UnitStruct` is private
   --> $DIR/struct.rs:32:32
    |
 LL |     let us_explicit = structs::UnitStruct;
-   |                                ^^^^^^^^^^
+   |                                ^^^^^^^^^^ this unit struct is private
+   |
+note: the unit struct `UnitStruct` is defined here
+  --> $DIR/auxiliary/structs.rs:8:1
+   |
+LL | pub struct UnitStruct;
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0639]: cannot create non-exhaustive struct using struct expression
   --> $DIR/struct.rs:7:14
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
index d9d6ea2..2a43875 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -2,31 +2,61 @@
   --> $DIR/variant.rs:11:48
    |
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
-   |                                                ^^^^^
+   |                                                ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
    |
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
-   |                                               ^^^^
+   |                                               ^^^^ this unit variant is private
+   |
+note: the unit variant `Unit` is defined here
+  --> $DIR/auxiliary/variants.rs:4:23
+   |
+LL |     #[non_exhaustive] Unit,
+   |                       ^^^^
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:18:32
    |
 LL |         NonExhaustiveVariants::Unit => "",
-   |                                ^^^^
+   |                                ^^^^ this unit variant is private
+   |
+note: the unit variant `Unit` is defined here
+  --> $DIR/auxiliary/variants.rs:4:23
+   |
+LL |     #[non_exhaustive] Unit,
+   |                       ^^^^
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:20:32
    |
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
-   |                                ^^^^^
+   |                                ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
    |
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
-   |                                   ^^^^^
+   |                                   ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26
diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
new file mode 100644
index 0000000..be13076
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
@@ -0,0 +1,38 @@
+// run-pass
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![feature(option_expect_none, option_unwrap_none)]
+
+//! Test that panic locations for `#[track_caller]` functions in std have the correct
+//! location reported.
+
+fn main() {
+    // inspect the `PanicInfo` we receive to ensure the right file is the source
+    std::panic::set_hook(Box::new(|info| {
+        let actual = info.location().unwrap();
+        if actual.file() != file!() {
+            eprintln!("expected a location in the test file, found {:?}", actual);
+            panic!();
+        }
+    }));
+
+    fn assert_panicked(f: impl FnOnce() + std::panic::UnwindSafe) {
+        std::panic::catch_unwind(f).unwrap_err();
+    }
+
+    let nope: Option<()> = None;
+    assert_panicked(|| nope.unwrap());
+    assert_panicked(|| nope.expect(""));
+
+    let yep: Option<()> = Some(());
+    assert_panicked(|| yep.unwrap_none());
+    assert_panicked(|| yep.expect_none(""));
+
+    let oops: Result<(), ()> = Err(());
+    assert_panicked(|| oops.unwrap());
+    assert_panicked(|| oops.expect(""));
+
+    let fine: Result<(), ()> = Ok(());
+    assert_panicked(|| fine.unwrap_err());
+    assert_panicked(|| fine.expect_err(""));
+}
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
new file mode 100644
index 0000000..0407eaf
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(track_caller)]
+
+fn pass_to_ptr_call<T>(f: fn(T), x: T) {
+    f(x);
+}
+
+#[track_caller]
+fn tracked_unit(_: ()) {
+    let expected_line = line!() - 1;
+    let location = std::panic::Location::caller();
+    assert_eq!(location.file(), file!());
+    assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+}
+
+fn main() {
+    pass_to_ptr_call(tracked_unit, ());
+}
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
new file mode 100644
index 0000000..a4baaa2
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(track_caller)]
+
+fn ptr_call(f: fn()) {
+    f();
+}
+
+#[track_caller]
+fn tracked() {
+    let expected_line = line!() - 1;
+    let location = std::panic::Location::caller();
+    assert_eq!(location.file(), file!());
+    assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
+}
+
+fn main() {
+    ptr_call(tracked);
+}
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
index 6498766..f5cb186 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
@@ -123,9 +123,11 @@
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions in this position are experimental [E0658]
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are experimental [E0658]
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR `let` expressions are not supported here
     #[cfg(FALSE)] (let 0 = 1);
     //~^ ERROR `let` expressions in this position are experimental [E0658]
     use_expr!(let 0 = 1);
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
index abe2009..c14a45a 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
@@ -1,5 +1,5 @@
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:131:15
+  --> $DIR/feature-gate.rs:133:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -260,7 +260,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are experimental
-  --> $DIR/feature-gate.rs:129:20
+  --> $DIR/feature-gate.rs:131:20
    |
 LL |     #[cfg(FALSE)] (let 0 = 1);
    |                    ^^^^^^^^^
@@ -287,7 +287,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are experimental
-  --> $DIR/feature-gate.rs:126:16
+  --> $DIR/feature-gate.rs:127:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -557,7 +557,16 @@
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/feature-gate.rs:126:16
+  --> $DIR/feature-gate.rs:123:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:127:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -565,6 +574,15 @@
    = note: only supported directly in conditions of `if`- and `while`-expressions
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
-error: aborting due to 63 previous errors
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:127:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: as well as when nested within `&&` and parenthesis in those conditions
+
+error: aborting due to 65 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr
new file mode 100644
index 0000000..e4f4d42
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/feature-gate.rs:16:1
+   |
+LL | fn main() {}
+   | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs
new file mode 100644
index 0000000..d600b53
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs
@@ -0,0 +1,16 @@
+// revisions: stock gated
+// gate-test-const_trait_bound_opt_out
+
+#![cfg_attr(gated, feature(const_trait_bound_opt_out))]
+#![allow(incomplete_features)]
+#![feature(rustc_attrs)]
+
+trait T {
+    const CONST: i32;
+}
+
+const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
+//[stock]~^ ERROR `?const` on trait bounds is experimental
+
+#[rustc_error]
+fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr
new file mode 100644
index 0000000..fbd3840
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `?const` on trait bounds is experimental
+  --> $DIR/feature-gate.rs:12:29
+   |
+LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
+   |                             ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67794
+   = help: add `#![feature(const_trait_bound_opt_out)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs
new file mode 100644
index 0000000..f5561a9
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs
@@ -0,0 +1,21 @@
+#![feature(const_trait_bound_opt_out)]
+#![feature(associated_type_bounds)]
+#![allow(incomplete_features)]
+
+trait T {}
+struct S;
+impl T for S {}
+
+fn rpit() -> impl ?const T { S }
+//~^ ERROR `?const` is not permitted in `impl Trait`
+
+fn apit(_: impl ?const T) {}
+//~^ ERROR `?const` is not permitted in `impl Trait`
+
+fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
+//~^ ERROR `?const` is not permitted in `impl Trait`
+
+fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
+//~^ ERROR `?const` is not permitted in `impl Trait`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr
new file mode 100644
index 0000000..06cd00a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr
@@ -0,0 +1,26 @@
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:9:19
+   |
+LL | fn rpit() -> impl ?const T { S }
+   |                   ^^^^^^^^
+
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:12:17
+   |
+LL | fn apit(_: impl ?const T) {}
+   |                 ^^^^^^^^
+
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:15:50
+   |
+LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
+   |                                                  ^^^^^^^^
+
+error: `?const` is not permitted in `impl Trait`
+  --> $DIR/in-impl-trait.rs:18:48
+   |
+LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
+   |                                                ^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs
new file mode 100644
index 0000000..fc9ed5b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs
@@ -0,0 +1,8 @@
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+trait Super {}
+trait T: ?const Super {}
+//~^ ERROR `?const` is not permitted in supertraits
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr
new file mode 100644
index 0000000..a0d8f95
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr
@@ -0,0 +1,8 @@
+error: `?const` is not permitted in supertraits
+  --> $DIR/in-trait-bounds.rs:5:10
+   |
+LL | trait T: ?const Super {}
+   |          ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs
new file mode 100644
index 0000000..b3d1f48
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs
@@ -0,0 +1,19 @@
+#![feature(const_trait_bound_opt_out)]
+#![allow(bare_trait_objects)]
+#![allow(incomplete_features)]
+
+struct S;
+trait T {}
+impl T for S {}
+
+// An inherent impl for the trait object `?const T`.
+impl ?const T {}
+//~^ ERROR `?const` is not permitted in trait objects
+
+fn trait_object() -> &'static dyn ?const T { &S }
+//~^ ERROR `?const` is not permitted in trait objects
+
+fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
+//~^ ERROR `?const` is not permitted in trait objects
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr
new file mode 100644
index 0000000..331fe04
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr
@@ -0,0 +1,20 @@
+error: `?const` is not permitted in trait objects
+  --> $DIR/in-trait-object.rs:10:6
+   |
+LL | impl ?const T {}
+   |      ^^^^^^^^
+
+error: `?const` is not permitted in trait objects
+  --> $DIR/in-trait-object.rs:13:35
+   |
+LL | fn trait_object() -> &'static dyn ?const T { &S }
+   |                                   ^^^^^^^^
+
+error: `?const` is not permitted in trait objects
+  --> $DIR/in-trait-object.rs:16:61
+   |
+LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
+   |                                                             ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs
new file mode 100644
index 0000000..01e941a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<T: ?const ?const Tr>;
+//~^ ERROR expected identifier, found keyword `const`
+//~| ERROR expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr
new file mode 100644
index 0000000..f7924b3
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found keyword `const`
+  --> $DIR/opt-out-twice.rs:6:21
+   |
+LL | struct S<T: ?const ?const Tr>;
+   |                     ^^^^^ expected identifier, found keyword
+
+error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr`
+  --> $DIR/opt-out-twice.rs:6:27
+   |
+LL | struct S<T: ?const ?const Tr>;
+   |                           ^^ expected one of 7 possible tokens
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs
new file mode 100644
index 0000000..a0d9610
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<
+    T: ?const ?for<'a> Tr<'a> + 'static + ?const std::ops::Add,
+    T: ?const ?for<'a: 'b> m::Trait<'a>,
+>;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs
new file mode 100644
index 0000000..c2c8689
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs
@@ -0,0 +1,7 @@
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
+//~^ ERROR `?const` and `?` are mutually exclusive
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr
new file mode 100644
index 0000000..e8e9d6c
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr
@@ -0,0 +1,8 @@
+error: `?const` and `?` are mutually exclusive
+  --> $DIR/with-maybe-sized.rs:4:13
+   |
+LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs
new file mode 100644
index 0000000..b904a2e
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs
@@ -0,0 +1,7 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+
+struct S<T: const Tr>;
+//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr
new file mode 100644
index 0000000..0dbca95
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found keyword `const`
+  --> $DIR/without-question-mark.rs:6:13
+   |
+LL | struct S<T: const Tr>;
+   |             ^^^^^ expected one of 9 possible tokens
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
new file mode 100644
index 0000000..b196f9e
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
@@ -0,0 +1,8 @@
+error: const trait impls are not yet implemented
+  --> $DIR/feature-gate.rs:9:1
+   |
+LL | impl const T for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
new file mode 100644
index 0000000..49b6c09
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
@@ -0,0 +1,13 @@
+// revisions: stock gated
+// gate-test-const_trait_impl
+
+#![cfg_attr(gated, feature(const_trait_impl))]
+#![allow(incomplete_features)]
+
+struct S;
+trait T {}
+impl const T for S {}
+//[stock]~^ ERROR const trait impls are experimental
+//[stock,gated]~^^ ERROR const trait impls are not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
new file mode 100644
index 0000000..093946f
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
@@ -0,0 +1,18 @@
+error[E0658]: const trait impls are experimental
+  --> $DIR/feature-gate.rs:9:6
+   |
+LL | impl const T for S {}
+   |      ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/67792
+   = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: const trait impls are not yet implemented
+  --> $DIR/feature-gate.rs:9:1
+   |
+LL | impl const T for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs
new file mode 100644
index 0000000..98d3a22
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs
@@ -0,0 +1,11 @@
+#![feature(const_trait_bound_opt_out)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+struct S;
+trait T {}
+
+impl ?const T for S {}
+//~^ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr
new file mode 100644
index 0000000..8f923ef
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+  --> $DIR/impl-opt-out-trait.rs:8:6
+   |
+LL | impl ?const T for S {}
+   |      ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs
new file mode 100644
index 0000000..7f064c0
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs
@@ -0,0 +1,17 @@
+#![feature(const_trait_impl)]
+#![feature(const_trait_bound_opt_out)]
+#![allow(incomplete_features)]
+#![allow(bare_trait_objects)]
+
+struct S;
+trait T {}
+
+impl const S {}
+//~^ ERROR inherent impls cannot be `const`
+//~| ERROR const trait impls are not yet implemented
+
+impl const T {}
+//~^ ERROR inherent impls cannot be `const`
+//~| ERROR const trait impls are not yet implemented
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
new file mode 100644
index 0000000..508c6f4
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
@@ -0,0 +1,30 @@
+error: inherent impls cannot be `const`
+  --> $DIR/inherent-impl.rs:9:1
+   |
+LL | impl const S {}
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: only trait implementations may be annotated with `const`
+
+error: inherent impls cannot be `const`
+  --> $DIR/inherent-impl.rs:13:1
+   |
+LL | impl const T {}
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: only trait implementations may be annotated with `const`
+
+error: const trait impls are not yet implemented
+  --> $DIR/inherent-impl.rs:9:1
+   |
+LL | impl const S {}
+   | ^^^^^^^^^^^^^^^
+
+error: const trait impls are not yet implemented
+  --> $DIR/inherent-impl.rs:13:1
+   |
+LL | impl const T {}
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs
new file mode 100644
index 0000000..354d48d
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_bound_opt_out)]
+#![feature(const_trait_impl)]
+#![allow(incomplete_features)]
+
+// For now, this parses since an error does not occur until AST lowering.
+impl ?const T {}
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs
index b8949ae..e9dcb4f 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.rs
@@ -21,6 +21,7 @@
     match WRAP_DIRECT_INLINE {
         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
     }
 }
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr
index c73a6cf..9c7d1f3 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-embedded.stderr
@@ -4,5 +4,11 @@
 LL |         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
    |         ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
+   |
+LL |         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs
index 584e7a0..ab1cb3b 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.rs
@@ -21,6 +21,7 @@
     match WRAP_DIRECT_PARAM {
         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
     }
 }
diff --git a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr
index 6fdf9db..6f49a8a 100644
--- a/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr
+++ b/src/test/ui/rfc1445/cant-hide-behind-direct-struct-param.stderr
@@ -4,5 +4,11 @@
 LL |         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
    |         ^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
+   |
+LL |         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/match-forbidden-without-eq.rs b/src/test/ui/rfc1445/match-forbidden-without-eq.rs
index 1cca275..59141ea 100644
--- a/src/test/ui/rfc1445/match-forbidden-without-eq.rs
+++ b/src/test/ui/rfc1445/match-forbidden-without-eq.rs
@@ -12,6 +12,7 @@
     match y {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { }
     }
 
diff --git a/src/test/ui/rfc1445/match-forbidden-without-eq.stderr b/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
index c05bb8f..b9476e3 100644
--- a/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
+++ b/src/test/ui/rfc1445/match-forbidden-without-eq.stderr
@@ -5,7 +5,7 @@
    |         ^^^
 
 warning: floating-point types cannot be used in patterns
-  --> $DIR/match-forbidden-without-eq.rs:20:9
+  --> $DIR/match-forbidden-without-eq.rs:21:9
    |
 LL |         f32::INFINITY => { }
    |         ^^^^^^^^^^^^^
@@ -14,8 +14,14 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-forbidden-without-eq.rs:13:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
 warning: floating-point types cannot be used in patterns
-  --> $DIR/match-forbidden-without-eq.rs:20:9
+  --> $DIR/match-forbidden-without-eq.rs:21:9
    |
 LL |         f32::INFINITY => { }
    |         ^^^^^^^^^^^^^
@@ -23,5 +29,5 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs
index 3d56fb0..9ef8a68 100644
--- a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs
+++ b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.rs
@@ -15,5 +15,6 @@
     match [B(1)] {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
     }
 }
diff --git a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr
index 371f8a0..7e354bf 100644
--- a/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr
+++ b/src/test/ui/rfc1445/match-nonempty-array-forbidden-without-eq.stderr
@@ -4,5 +4,11 @@
 LL |         FOO => { }
    |         ^^^
 
-error: aborting due to previous error
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
index 6b7d946..9530a1f 100644
--- a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
+++ b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.rs
@@ -16,6 +16,7 @@
     match y {
         FOO => { }
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => { }
     }
 }
diff --git a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
index 4157cf6..7ef0828 100644
--- a/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
+++ b/src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr
@@ -4,5 +4,11 @@
 LL |         FOO => { }
    |         ^^^
 
-error: aborting due to previous error
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr
index 171c00b..5b665e1 100644
--- a/src/test/ui/rfc1623.stderr
+++ b/src/test/ui/rfc1623.stderr
@@ -2,7 +2,7 @@
   --> $DIR/rfc1623.rs:8:42
    |
 LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
-   |                                          ^ expected lifetime parameter
+   |                                          ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
 
@@ -10,7 +10,7 @@
   --> $DIR/rfc1623.rs:10:39
    |
 LL |     &(non_elidable as fn(&u8, &u8) -> &u8);
-   |                                       ^ expected lifetime parameter
+   |                                       ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
 
diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
index 38b0941..33229a2 100644
--- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
+++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn slice_pat() {
     let sl: &[u8] = b"foo";
diff --git a/src/test/ui/rfcs/rfc1717/auxiliary/clibrary.rs b/src/test/ui/rfcs/rfc1717/auxiliary/clibrary.rs
deleted file mode 100644
index c1c5b70..0000000
--- a/src/test/ui/rfcs/rfc1717/auxiliary/clibrary.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// no-prefer-dynamic
-#![crate_type = "staticlib"]
-
-#[no_mangle]
-pub extern "C" fn foo(x:i32) -> i32 { x }
diff --git a/src/test/ui/rmeta-rpass.rs b/src/test/ui/rmeta-rpass.rs
index 5a63b5b..173a6a3 100644
--- a/src/test/ui/rmeta-rpass.rs
+++ b/src/test/ui/rmeta-rpass.rs
@@ -1,6 +1,11 @@
 // run-pass
 // Test that using rlibs and rmeta dep crates work together. Specifically, that
-// there can be both an rmeta and an rlib file and rustc will prefer the rlib.
+// there can be both an rmeta and an rlib file and rustc will prefer the rmeta
+// file.
+//
+// This behavior is simply making sure this doesn't accidentally change; in this
+// case we want to make sure that the rlib isn't being used as that would cause
+// bugs in -Zbinary-dep-depinfo (see #68298).
 
 // aux-build:rmeta-rmeta.rs
 // aux-build:rmeta-rlib-rpass.rs
@@ -9,5 +14,5 @@
 use rmeta_aux::Foo;
 
 pub fn main() {
-    let _ = Foo { field: 42 };
+    let _ = Foo { field2: 42 };
 }
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.rs b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
index 27d6dbf..0ca7fa3 100644
--- a/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.rs
@@ -6,6 +6,7 @@
 
 #[built_in_attr] //~ ERROR cannot use a built-in attribute through an import
 #[tool_mod::skip] //~ ERROR cannot use a tool module through an import
+                  //~| ERROR cannot use a tool module through an import
 fn main() {
     let _: built_in_type; // OK
 }
diff --git a/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
index fdde75f..45f77a0 100644
--- a/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/cross-crate.stderr
@@ -22,5 +22,17 @@
 LL | use cross_crate::*;
    |     ^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: cannot use a tool module through an import
+  --> $DIR/cross-crate.rs:8:3
+   |
+LL | #[tool_mod::skip]
+   |   ^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/cross-crate.rs:5:5
+   |
+LL | use cross_crate::*;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
index 541fc1b..44da71d 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.rs
@@ -15,5 +15,7 @@
 #[imported_inline] //~ ERROR cannot use a built-in attribute through an import
 #[builtin::imported_inline] //~ ERROR cannot use a built-in attribute through an import
 #[imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+                          //~| ERROR cannot use a tool module through an import
 #[tool_mod::imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+                                    //~| ERROR cannot use a tool module through an import
 fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
index fc64531..908bb49 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
@@ -29,7 +29,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: cannot use a tool module through an import
-  --> $DIR/prelude-fail-2.rs:18:13
+  --> $DIR/prelude-fail-2.rs:19:13
    |
 LL | #[tool_mod::imported_rustfmt::skip]
    |             ^^^^^^^^^^^^^^^^
@@ -40,5 +40,29 @@
 LL |     pub use rustfmt as imported_rustfmt;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: cannot use a tool module through an import
+  --> $DIR/prelude-fail-2.rs:17:3
+   |
+LL | #[imported_rustfmt::skip]
+   |   ^^^^^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/prelude-fail-2.rs:10:5
+   |
+LL | use rustfmt as imported_rustfmt;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+  --> $DIR/prelude-fail-2.rs:19:13
+   |
+LL | #[tool_mod::imported_rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^
+   |
+note: the tool module imported here
+  --> $DIR/prelude-fail-2.rs:12:13
+   |
+LL |     pub use rustfmt as imported_rustfmt;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/sanitizer-address.rs b/src/test/ui/sanitizer-address.rs
new file mode 100644
index 0000000..d27a30a
--- /dev/null
+++ b/src/test/ui/sanitizer-address.rs
@@ -0,0 +1,21 @@
+// needs-sanitizer-support
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=address -O
+//
+// run-fail
+// error-pattern: AddressSanitizer: stack-buffer-overflow
+// error-pattern: 'xs' <== Memory access at offset
+
+#![feature(test)]
+
+use std::hint::black_box;
+use std::mem;
+
+fn main() {
+    let xs = [0, 1, 2, 3];
+    // Avoid optimizing everything out.
+    let xs = black_box(xs.as_ptr());
+    let code = unsafe { *xs.offset(4) };
+    std::process::exit(code);
+}
diff --git a/src/test/ui/sanitizer-leak.rs b/src/test/ui/sanitizer-leak.rs
new file mode 100644
index 0000000..5c2f2cb
--- /dev/null
+++ b/src/test/ui/sanitizer-leak.rs
@@ -0,0 +1,21 @@
+// needs-sanitizer-support
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=leak -O
+//
+// run-fail
+// error-pattern: LeakSanitizer: detected memory leaks
+
+#![feature(test)]
+
+use std::hint::black_box;
+use std::mem;
+
+fn main() {
+    for _ in 0..10 {
+        let xs = vec![1, 2, 3];
+        // Prevent compiler from removing the memory allocation.
+        let xs = black_box(xs);
+        mem::forget(xs);
+    }
+}
diff --git a/src/test/ui/sanitizer-memory.rs b/src/test/ui/sanitizer-memory.rs
new file mode 100644
index 0000000..3e1cf45
--- /dev/null
+++ b/src/test/ui/sanitizer-memory.rs
@@ -0,0 +1,44 @@
+// needs-sanitizer-support
+// only-linux
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
+//
+// run-fail
+// error-pattern: MemorySanitizer: use-of-uninitialized-value
+// error-pattern: Uninitialized value was created by an allocation
+// error-pattern: in the stack frame of function 'random'
+//
+// This test case intentionally limits the usage of the std,
+// since it will be linked with an uninstrumented version of it.
+
+#![feature(core_intrinsics)]
+#![feature(start)]
+#![feature(test)]
+
+use std::hint::black_box;
+use std::mem::MaybeUninit;
+
+#[inline(never)]
+#[no_mangle]
+fn random() -> [isize; 32] {
+    let r = unsafe { MaybeUninit::uninit().assume_init() };
+    // Avoid optimizing everything out.
+    black_box(r)
+}
+
+#[inline(never)]
+#[no_mangle]
+fn xor(a: &[isize]) -> isize {
+    let mut s = 0;
+    for i in 0..a.len() {
+        s = s ^ a[i];
+    }
+    s
+}
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    let r = random();
+    xor(&r)
+}
diff --git a/src/test/ui/sanitizer-unsupported-target.rs b/src/test/ui/sanitizer-unsupported-target.rs
new file mode 100644
index 0000000..444333c
--- /dev/null
+++ b/src/test/ui/sanitizer-unsupported-target.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
+// error-pattern: error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
diff --git a/src/test/ui/sanitizer-unsupported-target.stderr b/src/test/ui/sanitizer-unsupported-target.stderr
new file mode 100644
index 0000000..38be58d
--- /dev/null
+++ b/src/test/ui/sanitizer-unsupported-target.stderr
@@ -0,0 +1,4 @@
+error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target
+
+error: aborting due to previous error
+
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
index dec5809..96401cb 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `A` in the current scope
+error[E0599]: no method named `foo` found for struct `A` in the current scope
   --> $DIR/point-at-arbitrary-self-type-method.rs:8:7
    |
 LL | struct A;
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
index e93c4da..28a7b68 100644
--- 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
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `A` in the current scope
+error[E0599]: no method named `foo` found for struct `A` in the current scope
   --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7
    |
 LL | trait B { fn foo(self: Box<Self>); }
diff --git a/src/test/ui/self/suggest-self-2.rs b/src/test/ui/self/suggest-self-2.rs
index d6bf543..1e00182 100644
--- a/src/test/ui/self/suggest-self-2.rs
+++ b/src/test/ui/self/suggest-self-2.rs
@@ -18,7 +18,7 @@
         //~^ ERROR cannot find function `bar` in this scope
 
         self.bar();
-        //~^ ERROR no method named `bar` found for type
+        //~^ ERROR no method named `bar` found for reference
     }
 }
 
diff --git a/src/test/ui/self/suggest-self-2.stderr b/src/test/ui/self/suggest-self-2.stderr
index 452c312..4bd025e 100644
--- a/src/test/ui/self/suggest-self-2.stderr
+++ b/src/test/ui/self/suggest-self-2.stderr
@@ -28,7 +28,7 @@
 LL |         bar();
    |         ^^^ not found in this scope
 
-error[E0599]: no method named `bar` found for type `&Foo` in the current scope
+error[E0599]: no method named `bar` found for reference `&Foo` in the current scope
   --> $DIR/suggest-self-2.rs:20:14
    |
 LL |         self.bar();
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr
index 3597cc5..362907e 100644
--- a/src/test/ui/shadowed/shadowed-trait-methods.stderr
+++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `f` found for type `()` in the current scope
+error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/shadowed-trait-methods.rs:13:8
    |
 LL |     ().f()
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.rs b/src/test/ui/shadowed/shadowed-use-visibility.rs
index 8185e82..6b80197 100644
--- a/src/test/ui/shadowed/shadowed-use-visibility.rs
+++ b/src/test/ui/shadowed/shadowed-use-visibility.rs
@@ -6,11 +6,11 @@
 }
 
 mod bar {
-    use foo::bar::f as g; //~ ERROR module `bar` is private
+    use foo::bar::f as g; //~ ERROR module import `bar` is private
 
     use foo as f;
     pub use foo::*;
 }
 
-use bar::f::f; //~ ERROR module `f` is private
+use bar::f::f; //~ ERROR module import `f` is private
 fn main() {}
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr
index 7c66fdf..cd8ec13 100644
--- a/src/test/ui/shadowed/shadowed-use-visibility.stderr
+++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr
@@ -1,14 +1,26 @@
-error[E0603]: module `bar` is private
+error[E0603]: module import `bar` is private
   --> $DIR/shadowed-use-visibility.rs:9:14
    |
 LL |     use foo::bar::f as g;
-   |              ^^^
+   |              ^^^ this module import is private
+   |
+note: the module import `bar` is defined here
+  --> $DIR/shadowed-use-visibility.rs:4:9
+   |
+LL |     use foo as bar;
+   |         ^^^^^^^^^^
 
-error[E0603]: module `f` is private
+error[E0603]: module import `f` is private
   --> $DIR/shadowed-use-visibility.rs:15:10
    |
 LL | use bar::f::f;
-   |          ^
+   |          ^ this module import is private
+   |
+note: the module import `f` is defined here
+  --> $DIR/shadowed-use-visibility.rs:11:9
+   |
+LL |     use foo as f;
+   |         ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs
index 8f1599a..89b8eba 100644
--- a/src/test/ui/span/issue-43927-non-ADT-derive.rs
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.rs
@@ -5,6 +5,9 @@
 //~| ERROR cannot determine resolution for the derive macro `Debug`
 //~| ERROR cannot determine resolution for the derive macro `PartialEq`
 //~| ERROR cannot determine resolution for the derive macro `Eq`
+//~| ERROR cannot determine resolution for the derive macro `Debug`
+//~| ERROR cannot determine resolution for the derive macro `PartialEq`
+//~| ERROR cannot determine resolution for the derive macro `Eq`
 struct DerivedOn;
 
 fn main() {}
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
index 47ce718..b68681c 100644
--- a/src/test/ui/span/issue-43927-non-ADT-derive.stderr
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
@@ -28,5 +28,29 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 4 previous errors
+error: cannot determine resolution for the derive macro `Eq`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:29
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |                             ^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `PartialEq`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:18
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |                  ^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `Debug`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:11
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |           ^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/span/issue-7575.rs b/src/test/ui/span/issue-7575.rs
index ea0a665..eddd158 100644
--- a/src/test/ui/span/issue-7575.rs
+++ b/src/test/ui/span/issue-7575.rs
@@ -60,15 +60,15 @@
 
 fn no_param_bound(u: usize, m: Myisize) -> usize {
     u.f8(42) + u.f9(342) + m.fff(42)
-            //~^ ERROR no method named `f9` found for type `usize` in the current scope
-            //~| ERROR no method named `fff` found for type `Myisize` in the current scope
+            //~^ ERROR no method named `f9` found
+            //~| ERROR no method named `fff` found
 
 
 }
 
 fn param_bound<T: ManyImplTrait>(t: T) -> bool {
     t.is_str()
-    //~^ ERROR no method named `is_str` found for type `T` in the current scope
+    //~^ ERROR no method named `is_str` found
 }
 
 fn main() {
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index 53a62384..eb85be0 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -38,7 +38,7 @@
 LL |     u.f8(42) + UnusedTrait::f9(u, 342) + m.fff(42)
    |                ^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `fff` found for type `Myisize` in the current scope
+error[E0599]: no method named `fff` found for struct `Myisize` in the current scope
   --> $DIR/issue-7575.rs:62:30
    |
 LL | struct Myisize(isize);
@@ -57,7 +57,7 @@
 LL |     fn fff(i: isize) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `is_str` found for type `T` in the current scope
+error[E0599]: no method named `is_str` found for type parameter `T` in the current scope
   --> $DIR/issue-7575.rs:70:7
    |
 LL |     t.is_str()
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
index 34a1416..5c10444 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -20,5 +20,5 @@
 
 fn main() {
     println!("{}", MyStruct.foo_one());
-    //~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
+    //~^ ERROR no method named `foo_one` found
 }
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 bbfe4c3..1980977 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo_one` found for type `MyStruct` in the current scope
+error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
   --> $DIR/specialization-trait-not-implemented.rs:22:29
    |
 LL | struct MyStruct;
diff --git a/src/test/ui/stability-in-private-module.rs b/src/test/ui/stability-in-private-module.rs
index f12e919..1815897 100644
--- a/src/test/ui/stability-in-private-module.rs
+++ b/src/test/ui/stability-in-private-module.rs
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 fn main() {
     let _ = std::thread::thread_info::current_thread();
     //~^ERROR module `thread_info` is private
diff --git a/src/test/ui/stability-in-private-module.stderr b/src/test/ui/stability-in-private-module.stderr
index c3edd62..3a97416 100644
--- a/src/test/ui/stability-in-private-module.stderr
+++ b/src/test/ui/stability-in-private-module.stderr
@@ -1,8 +1,14 @@
 error[E0603]: module `thread_info` is private
-  --> $DIR/stability-in-private-module.rs:2:26
+  --> $DIR/stability-in-private-module.rs:7:26
    |
 LL |     let _ = std::thread::thread_info::current_thread();
-   |                          ^^^^^^^^^^^
+   |                          ^^^^^^^^^^^ this module is private
+   |
+note: the module `thread_info` is defined here
+  --> $SRC_DIR/libstd/thread/mod.rs:LL:COL
+   |
+LL | use crate::sys_common::thread_info;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/static/static-priv-by-default2.stderr b/src/test/ui/static/static-priv-by-default2.stderr
index 95bcf07..f6cd404 100644
--- a/src/test/ui/static/static-priv-by-default2.stderr
+++ b/src/test/ui/static/static-priv-by-default2.stderr
@@ -2,13 +2,25 @@
   --> $DIR/static-priv-by-default2.rs:15:30
    |
 LL |     use child::childs_child::private;
-   |                              ^^^^^^^
+   |                              ^^^^^^^ this static is private
+   |
+note: the static `private` is defined here
+  --> $DIR/static-priv-by-default2.rs:7:9
+   |
+LL |         static private: isize = 0;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: static `private` is private
   --> $DIR/static-priv-by-default2.rs:23:33
    |
 LL |     use static_priv_by_default::private;
-   |                                 ^^^^^^^
+   |                                 ^^^^^^^ this static is private
+   |
+note: the static `private` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:3:1
+   |
+LL | static private: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/structs/struct-variant-privacy-xc.stderr b/src/test/ui/structs/struct-variant-privacy-xc.stderr
index 39241b6..0203b7b 100644
--- a/src/test/ui/structs/struct-variant-privacy-xc.stderr
+++ b/src/test/ui/structs/struct-variant-privacy-xc.stderr
@@ -2,13 +2,25 @@
   --> $DIR/struct-variant-privacy-xc.rs:4:33
    |
 LL | fn f(b: struct_variant_privacy::Bar) {
-   |                                 ^^^
+   |                                 ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy-xc.rs:6:33
    |
 LL |         struct_variant_privacy::Bar::Baz { a: _a } => {}
-   |                                 ^^^
+   |                                 ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/structs/struct-variant-privacy.stderr b/src/test/ui/structs/struct-variant-privacy.stderr
index 127a650..d1b603f 100644
--- a/src/test/ui/structs/struct-variant-privacy.stderr
+++ b/src/test/ui/structs/struct-variant-privacy.stderr
@@ -2,13 +2,25 @@
   --> $DIR/struct-variant-privacy.rs:7:14
    |
 LL | fn f(b: foo::Bar) {
-   |              ^^^
+   |              ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/struct-variant-privacy.rs:2:5
+   |
+LL |     enum Bar {
+   |     ^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy.rs:9:14
    |
 LL |         foo::Bar::Baz { a: _a } => {}
-   |              ^^^
+   |              ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/struct-variant-privacy.rs:2:5
+   |
+LL |     enum Bar {
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/suffixed-literal-meta.rs
index a653149..c3a4eab 100644
--- a/src/test/ui/suffixed-literal-meta.rs
+++ b/src/test/ui/suffixed-literal-meta.rs
@@ -1,15 +1,27 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
+                     //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
+                     //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
+                      //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
+                        //~| ERROR: suffixed literals are not allowed in attributes
 fn main() {}
diff --git a/src/test/ui/suffixed-literal-meta.stderr b/src/test/ui/suffixed-literal-meta.stderr
index 83de173..84fe91d 100644
--- a/src/test/ui/suffixed-literal-meta.stderr
+++ b/src/test/ui/suffixed-literal-meta.stderr
@@ -4,95 +4,191 @@
 LL | #[rustc_dummy = 1usize]
    |                 ^^^^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
-
-error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:4:17
-   |
-LL | #[rustc_dummy = 1u8]
-   |                 ^^^
-   |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: suffixed literals are not allowed in attributes
   --> $DIR/suffixed-literal-meta.rs:5:17
    |
-LL | #[rustc_dummy = 1u16]
-   |                 ^^^^
+LL | #[rustc_dummy = 1u8]
+   |                 ^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
-
-error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:6:17
-   |
-LL | #[rustc_dummy = 1u32]
-   |                 ^^^^
-   |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: suffixed literals are not allowed in attributes
   --> $DIR/suffixed-literal-meta.rs:7:17
    |
-LL | #[rustc_dummy = 1u64]
+LL | #[rustc_dummy = 1u16]
    |                 ^^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
-
-error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:8:17
-   |
-LL | #[rustc_dummy = 1isize]
-   |                 ^^^^^^
-   |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: suffixed literals are not allowed in attributes
   --> $DIR/suffixed-literal-meta.rs:9:17
    |
-LL | #[rustc_dummy = 1i8]
-   |                 ^^^
-   |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
-
-error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:10:17
-   |
-LL | #[rustc_dummy = 1i16]
+LL | #[rustc_dummy = 1u32]
    |                 ^^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: suffixed literals are not allowed in attributes
   --> $DIR/suffixed-literal-meta.rs:11:17
    |
-LL | #[rustc_dummy = 1i32]
+LL | #[rustc_dummy = 1u64]
    |                 ^^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
-
-error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:12:17
-   |
-LL | #[rustc_dummy = 1i64]
-   |                 ^^^^
-   |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: suffixed literals are not allowed in attributes
   --> $DIR/suffixed-literal-meta.rs:13:17
    |
+LL | #[rustc_dummy = 1isize]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:15:17
+   |
+LL | #[rustc_dummy = 1i8]
+   |                 ^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:17:17
+   |
+LL | #[rustc_dummy = 1i16]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:19:17
+   |
+LL | #[rustc_dummy = 1i32]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:21:17
+   |
+LL | #[rustc_dummy = 1i64]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:23:17
+   |
 LL | #[rustc_dummy = 1.0f32]
    |                 ^^^^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: suffixed literals are not allowed in attributes
-  --> $DIR/suffixed-literal-meta.rs:14:17
+  --> $DIR/suffixed-literal-meta.rs:25:17
    |
 LL | #[rustc_dummy = 1.0f64]
    |                 ^^^^^^
    |
-   = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.).
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
-error: aborting due to 12 previous errors
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:3:17
+   |
+LL | #[rustc_dummy = 1usize]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:5:17
+   |
+LL | #[rustc_dummy = 1u8]
+   |                 ^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:7:17
+   |
+LL | #[rustc_dummy = 1u16]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:9:17
+   |
+LL | #[rustc_dummy = 1u32]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:11:17
+   |
+LL | #[rustc_dummy = 1u64]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:13:17
+   |
+LL | #[rustc_dummy = 1isize]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:15:17
+   |
+LL | #[rustc_dummy = 1i8]
+   |                 ^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:17:17
+   |
+LL | #[rustc_dummy = 1i16]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:19:17
+   |
+LL | #[rustc_dummy = 1i32]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:21:17
+   |
+LL | #[rustc_dummy = 1i64]
+   |                 ^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:23:17
+   |
+LL | #[rustc_dummy = 1.0f32]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: suffixed literals are not allowed in attributes
+  --> $DIR/suffixed-literal-meta.rs:25:17
+   |
+LL | #[rustc_dummy = 1.0f64]
+   |                 ^^^^^^
+   |
+   = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs
index 7c8231b..e1e3317 100644
--- a/src/test/ui/suggestions/attribute-typos.rs
+++ b/src/test/ui/suggestions/attribute-typos.rs
@@ -1,3 +1,7 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
 #[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope
 fn foo() {}
 
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index e403293..a094359 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -1,5 +1,5 @@
 error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
-  --> $DIR/attribute-typos.rs:7:3
+  --> $DIR/attribute-typos.rs:11:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^
@@ -8,19 +8,24 @@
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: cannot find attribute `rustc_err` in this scope
-  --> $DIR/attribute-typos.rs:7:3
+  --> $DIR/attribute-typos.rs:11:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
 
 error: cannot find attribute `tests` in this scope
-  --> $DIR/attribute-typos.rs:4:3
+  --> $DIR/attribute-typos.rs:8:3
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
+   | 
+  ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
+   |
+LL |     pub macro test($item:item) {
+   |     -------------------------- similarly named attribute macro `test` defined here
 
 error: cannot find attribute `deprcated` in this scope
-  --> $DIR/attribute-typos.rs:1:3
+  --> $DIR/attribute-typos.rs:5:3
    |
 LL | #[deprcated]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed
index dda9e93..f292f27 100644
--- a/src/test/ui/suggestions/constrain-trait.fixed
+++ b/src/test/ui/suggestions/constrain-trait.fixed
@@ -12,13 +12,13 @@
 
 trait UseString: std::fmt::Debug + GetString {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
 trait UseString2: GetString {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs
index 4ef0eff..99ccf7a 100644
--- a/src/test/ui/suggestions/constrain-trait.rs
+++ b/src/test/ui/suggestions/constrain-trait.rs
@@ -12,13 +12,13 @@
 
 trait UseString: std::fmt::Debug {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
 trait UseString2 {
     fn use_string(&self) {
-        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+        println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found
     }
 }
 
diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr
index 3cc351a..f1c50e5 100644
--- a/src/test/ui/suggestions/constrain-trait.stderr
+++ b/src/test/ui/suggestions/constrain-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
   --> $DIR/constrain-trait.rs:15:31
    |
 LL |         println!("{:?}", self.get_a());
@@ -10,7 +10,7 @@
 LL | trait UseString: std::fmt::Debug + GetString {
    |                                  ^^^^^^^^^^^
 
-error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+error[E0599]: no method named `get_a` found for reference `&Self` in the current scope
   --> $DIR/constrain-trait.rs:21:31
    |
 LL |         println!("{:?}", self.get_a());
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 2f0a457..232e54b 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -236,7 +236,7 @@
   --> $DIR/fn-or-tuple-struct-without-args.rs:46:20
    |
 LL |     let closure = || 42;
-   |                   -- closure defined here
+   |                   ----- the found closure
 LL |     let _: usize = closure;
    |            -----   ^^^^^^^
    |            |       |
diff --git a/src/test/ui/suggestions/for-i-in-vec.fixed b/src/test/ui/suggestions/for-i-in-vec.fixed
new file mode 100644
index 0000000..ec7358b
--- /dev/null
+++ b/src/test/ui/suggestions/for-i-in-vec.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Foo {
+    v: Vec<u32>,
+}
+
+impl Foo {
+    fn bar(&self) {
+        for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/for-i-in-vec.rs b/src/test/ui/suggestions/for-i-in-vec.rs
new file mode 100644
index 0000000..304fe8c
--- /dev/null
+++ b/src/test/ui/suggestions/for-i-in-vec.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Foo {
+    v: Vec<u32>,
+}
+
+impl Foo {
+    fn bar(&self) {
+        for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/for-i-in-vec.stderr b/src/test/ui/suggestions/for-i-in-vec.stderr
new file mode 100644
index 0000000..576a7cc
--- /dev/null
+++ b/src/test/ui/suggestions/for-i-in-vec.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of `self.v` which is behind a shared reference
+  --> $DIR/for-i-in-vec.rs:10:18
+   |
+LL |         for _ in self.v {
+   |                  ^^^^^^
+   |                  |
+   |                  move occurs because `self.v` has type `std::vec::Vec<u32>`, which does not implement the `Copy` trait
+   |                  help: consider iterating over a slice of the `Vec<_>`'s content: `&self.v`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
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 4aec720..db54d04 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
@@ -1,4 +1,4 @@
-error[E0599]: no method named `hello` found for type `impl Foo` in the current scope
+error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope
   --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9
    |
 LL |     foo.hello();
diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr
index f2496f6..14c7b18 100644
--- a/src/test/ui/suggestions/issue-21673.stderr
+++ b/src/test/ui/suggestions/issue-21673.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for type `&T` in the current scope
+error[E0599]: no method named `method` found for reference `&T` in the current scope
   --> $DIR/issue-21673.rs:6:7
    |
 LL |     x.method()
@@ -10,7 +10,7 @@
 LL | fn call_method<T: Foo + std::fmt::Debug>(x: &T) {
    |                ^^^^^^^^
 
-error[E0599]: no method named `method` found for type `T` in the current scope
+error[E0599]: no method named `method` found for type parameter `T` in the current scope
   --> $DIR/issue-21673.rs:10:7
    |
 LL |     x.method()
diff --git a/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs
new file mode 100644
index 0000000..440bb65
--- /dev/null
+++ b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let a_longer_variable_name = 1;
+    println!("{}", a_variable_longer_name); //~ ERROR E0425
+}
diff --git a/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr
new file mode 100644
index 0000000..d7b33ea
--- /dev/null
+++ b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `a_variable_longer_name` in this scope
+  --> $DIR/issue-66968-suggest-sorted-words.rs:3:20
+   |
+LL |     println!("{}", a_variable_longer_name);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `a_longer_variable_name`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
index dcef2ad..f8b8637 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs
@@ -19,5 +19,5 @@
     //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
     //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
 
-    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type
+    writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for struct
 }
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index daa8e11..2c3c07c 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -25,7 +25,7 @@
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
    = note: required by `std::io::BufWriter`
 
-error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope
+error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope
   --> $DIR/mut-borrow-needed-by-trait.rs:22:5
    |
 LL |     writeln!(fp, "hello world").unwrap();
diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr
index 1465b9e..167d61b 100644
--- a/src/test/ui/suggestions/opaque-type-error.stderr
+++ b/src/test/ui/suggestions/opaque-type-error.stderr
@@ -1,6 +1,9 @@
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/opaque-type-error.rs:20:9
    |
+LL |   fn thing_two() -> impl Future<Output = Result<(), ()>> {
+   |                     ------------------------------------ the found opaque type
+...
 LL | /     if true {
 LL | |         thing_one()
    | |         ----------- expected because of this
diff --git a/src/test/ui/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs
index d10300b..289a784 100644
--- a/src/test/ui/suggestions/remove-as_str.rs
+++ b/src/test/ui/suggestions/remove-as_str.rs
@@ -1,21 +1,21 @@
 fn foo1(s: &str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo2<'a>(s: &'a str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&'a str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo3(s: &mut str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&mut str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn foo4(s: &&str) {
     s.as_str();
-    //~^ ERROR no method named `as_str` found for type `&&str` in the current scope
+    //~^ ERROR no method named `as_str` found
 }
 
 fn main() {}
diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr
index eae9cc0..534c497 100644
--- a/src/test/ui/suggestions/remove-as_str.stderr
+++ b/src/test/ui/suggestions/remove-as_str.stderr
@@ -1,22 +1,22 @@
-error[E0599]: no method named `as_str` found for type `&str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&str` in the current scope
   --> $DIR/remove-as_str.rs:2:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&'a str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&'a str` in the current scope
   --> $DIR/remove-as_str.rs:7:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&mut str` in the current scope
+error[E0599]: no method named `as_str` found for mutable reference `&mut str` in the current scope
   --> $DIR/remove-as_str.rs:12:7
    |
 LL |     s.as_str();
    |      -^^^^^^-- help: remove this method call
 
-error[E0599]: no method named `as_str` found for type `&&str` in the current scope
+error[E0599]: no method named `as_str` found for reference `&&str` in the current scope
   --> $DIR/remove-as_str.rs:17:7
    |
 LL |     s.as_str();
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
index 5480adb..f738a1f 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
@@ -9,5 +9,5 @@
     let shared_state = RefCell::new(HasAssocMethod);
     let state = shared_state.borrow_mut();
     state.hello();
-    //~^ ERROR no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>`
+    //~^ ERROR no method named `hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
index a1c0126..507f822 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
+error[E0599]: no method named `hello` found for struct `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
   --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
    |
 LL |     state.hello();
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
index ef4b38d..2a829db 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
@@ -7,5 +7,5 @@
 fn main() {
     let x = GenericAssocMethod(33i32);
     x.default_hello();
-    //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod<i32>`
+    //~^ ERROR no method named `default_hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
index 8cfa7de..dfc1887 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `default_hello` found for type `GenericAssocMethod<i32>` in the current scope
+error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope
   --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7
    |
 LL | struct GenericAssocMethod<T>(T);
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index 4678410..a715c56 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `bat` found for type `Foo` in the current scope
+error[E0599]: no method named `bat` found for struct `Foo` in the current scope
   --> $DIR/suggest-methods.rs:18:7
    |
 LL | struct Foo;
@@ -7,7 +7,7 @@
 LL |     f.bat(1.0);
    |       ^^^ help: there is a method with a similar name: `bar`
 
-error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
+error[E0599]: no method named `is_emtpy` found for struct `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy();
diff --git a/src/test/ui/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs
index d418834..dd05d0f 100644
--- a/src/test/ui/suggestions/suggest-variants.rs
+++ b/src/test/ui/suggestions/suggest-variants.rs
@@ -9,9 +9,9 @@
 }
 
 fn main() {
-    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant `Squareee`
-    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant `Circl`
-    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant `Rombus`
+    println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant named `Squareee`
+    println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant named `Circl`
+    println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant named `Rombus`
     Shape::Squareee; //~ ERROR no variant
     Shape::Circl; //~ ERROR no variant
     Shape::Rombus; //~ ERROR no variant
diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr
index b4338e2..9227baa 100644
--- a/src/test/ui/suggestions/suggest-variants.stderr
+++ b/src/test/ui/suggestions/suggest-variants.stderr
@@ -1,4 +1,4 @@
-error: no variant `Squareee` in enum `Shape`
+error[E0599]: no variant named `Squareee` found for enum `Shape`
   --> $DIR/suggest-variants.rs:12:41
    |
 LL | enum Shape {
@@ -7,7 +7,7 @@
 LL |     println!("My shape is {:?}", Shape::Squareee { size: 5});
    |                                         ^^^^^^^^ help: there is a variant with a similar name: `Square`
 
-error: no variant `Circl` in enum `Shape`
+error[E0599]: no variant named `Circl` found for enum `Shape`
   --> $DIR/suggest-variants.rs:13:41
    |
 LL | enum Shape {
@@ -16,7 +16,7 @@
 LL |     println!("My shape is {:?}", Shape::Circl { size: 5});
    |                                         ^^^^^ help: there is a variant with a similar name: `Circle`
 
-error: no variant `Rombus` in enum `Shape`
+error[E0599]: no variant named `Rombus` found for enum `Shape`
   --> $DIR/suggest-variants.rs:14:41
    |
 LL | enum Shape {
@@ -25,7 +25,7 @@
 LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
    |                                         ^^^^^^ variant not found in `Shape`
 
-error[E0599]: no variant or associated item named `Squareee` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Squareee` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:15:12
    |
 LL | enum Shape {
@@ -37,7 +37,7 @@
    |            variant or associated item not found in `Shape`
    |            help: there is a variant with a similar name: `Square`
 
-error[E0599]: no variant or associated item named `Circl` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:16:12
    |
 LL | enum Shape {
@@ -49,7 +49,7 @@
    |            variant or associated item not found in `Shape`
    |            help: there is a variant with a similar name: `Circle`
 
-error[E0599]: no variant or associated item named `Rombus` found for type `Shape` in the current scope
+error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:17:12
    |
 LL | enum Shape {
diff --git a/src/test/ui/super-at-top-level.rs b/src/test/ui/super-at-top-level.rs
index 41360df..e4d587b 100644
--- a/src/test/ui/super-at-top-level.rs
+++ b/src/test/ui/super-at-top-level.rs
@@ -1,4 +1,4 @@
-use super::f; //~ ERROR there are too many initial `super`s
+use super::f; //~ ERROR there are too many leading `super` keywords
 
 fn main() {
 }
diff --git a/src/test/ui/super-at-top-level.stderr b/src/test/ui/super-at-top-level.stderr
index d04ce38..23613df 100644
--- a/src/test/ui/super-at-top-level.stderr
+++ b/src/test/ui/super-at-top-level.stderr
@@ -1,8 +1,8 @@
-error[E0433]: failed to resolve: there are too many initial `super`s.
+error[E0433]: failed to resolve: there are too many leading `super` keywords
   --> $DIR/super-at-top-level.rs:1:5
    |
 LL | use super::f;
-   |     ^^^^^ there are too many initial `super`s.
+   |     ^^^^^ there are too many leading `super` keywords
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr
index 53ab2f9..33cacaf 100644
--- a/src/test/ui/symbol-names/impl1.legacy.stderr
+++ b/src/test/ui/symbol-names/impl1.legacy.stderr
@@ -1,71 +1,71 @@
 error: symbol-name(_ZN5impl13foo3Foo3bar17h92cf46db76791039E)
-  --> $DIR/impl1.rs:14:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(impl1::foo::Foo::bar::h92cf46db76791039)
-  --> $DIR/impl1.rs:14:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(impl1::foo::Foo::bar)
-  --> $DIR/impl1.rs:14:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(foo::Foo::bar)
-  --> $DIR/impl1.rs:21:9
+  --> $DIR/impl1.rs:23:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h90c4a800b1aa0df0E)
-  --> $DIR/impl1.rs:32:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(impl1::bar::<impl impl1::foo::Foo>::baz::h90c4a800b1aa0df0)
-  --> $DIR/impl1.rs:32:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
-  --> $DIR/impl1.rs:32:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(bar::<impl foo::Foo>::baz)
-  --> $DIR/impl1.rs:39:9
+  --> $DIR/impl1.rs:41:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h92c563325b7ff21aE)
-  --> $DIR/impl1.rs:62:13
+error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17SYMBOL_HASHE)
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h92c563325b7ff21a)
-  --> $DIR/impl1.rs:62:13
+error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::SYMBOL_HASH)
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method)
-  --> $DIR/impl1.rs:62:13
+error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
-  --> $DIR/impl1.rs:69:13
+error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{{closure}}#1::Bar>::method)
+  --> $DIR/impl1.rs:71:13
    |
 LL |             #[rustc_def_path]
    |             ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index c1aaec5..1f689a5 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -3,6 +3,8 @@
 // revisions: legacy v0
 //[legacy]compile-flags: -Z symbol-mangling-version=legacy
     //[v0]compile-flags: -Z symbol-mangling-version=v0
+//[legacy]normalize-stderr-32bit: "hdb62078998ce7ea8" -> "SYMBOL_HASH"
+//[legacy]normalize-stderr-64bit: "h62e540f14f879d56" -> "SYMBOL_HASH"
 
 #![feature(optin_builtin_traits, rustc_attrs)]
 #![allow(dead_code)]
@@ -60,15 +62,15 @@
         // Test type mangling, by putting them in an `impl` header.
         impl Bar for [&'_ (dyn Foo<Assoc = extern fn(&u8, ...)> + AutoTrait); 3] {
             #[rustc_symbol_name]
-            //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
-            //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method
-            //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method)
+            //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
+            //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method
+            //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
              //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
                 //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
                 //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
             #[rustc_def_path]
-            //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
-               //[v0]~^^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
+            //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{{closure}}#1::Bar>::method)
+               //[v0]~^^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{{closure}}#1::Bar>::method)
             fn method(&self) {}
         }
     };
diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr
index a931937..b6a35d9 100644
--- a/src/test/ui/symbol-names/impl1.v0.stderr
+++ b/src/test/ui/symbol-names/impl1.v0.stderr
@@ -1,71 +1,71 @@
 error: symbol-name(_RNvMNtCs4fqI2P2rA04_5impl13fooNtB2_3Foo3bar)
-  --> $DIR/impl1.rs:14:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<impl1[317d481089b8c8fe]::foo::Foo>::bar)
-  --> $DIR/impl1.rs:14:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<impl1::foo::Foo>::bar)
-  --> $DIR/impl1.rs:14:9
+  --> $DIR/impl1.rs:16:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(foo::Foo::bar)
-  --> $DIR/impl1.rs:21:9
+  --> $DIR/impl1.rs:23:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_RNvMNtCs4fqI2P2rA04_5impl13barNtNtB4_3foo3Foo3baz)
-  --> $DIR/impl1.rs:32:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<impl1[317d481089b8c8fe]::foo::Foo>::baz)
-  --> $DIR/impl1.rs:32:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<impl1::foo::Foo>::baz)
-  --> $DIR/impl1.rs:32:9
+  --> $DIR/impl1.rs:34:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: def-path(bar::<impl foo::Foo>::baz)
-  --> $DIR/impl1.rs:39:9
+  --> $DIR/impl1.rs:41:9
    |
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
 error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-  --> $DIR/impl1.rs:62:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:62:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
 error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
-  --> $DIR/impl1.rs:62:13
+  --> $DIR/impl1.rs:64:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method)
-  --> $DIR/impl1.rs:69:13
+error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{{closure}}#1::Bar>::method)
+  --> $DIR/impl1.rs:71:13
    |
 LL |             #[rustc_def_path]
    |             ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/test-attrs/test-should-panic-attr.stderr b/src/test/ui/test-attrs/test-should-panic-attr.stderr
index 4b032eb..d7d0d84 100644
--- a/src/test/ui/test-attrs/test-should-panic-attr.stderr
+++ b/src/test/ui/test-attrs/test-should-panic-attr.stderr
@@ -4,7 +4,7 @@
 LL | #[should_panic(expected)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+   = note: errors in this attribute were erroneously allowed and will become a hard error in a future release.
 
 warning: argument must be of the form: `expected = "error message"`
   --> $DIR/test-should-panic-attr.rs:18:1
@@ -12,7 +12,7 @@
 LL | #[should_panic(expect)]
    | ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+   = note: errors in this attribute were erroneously allowed and will become a hard error in a future release.
 
 warning: argument must be of the form: `expected = "error message"`
   --> $DIR/test-should-panic-attr.rs:25:1
@@ -20,7 +20,7 @@
 LL | #[should_panic(expected(foo, bar))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+   = note: errors in this attribute were erroneously allowed and will become a hard error in a future release.
 
 warning: argument must be of the form: `expected = "error message"`
   --> $DIR/test-should-panic-attr.rs:32:1
@@ -28,5 +28,5 @@
 LL | #[should_panic(expected = "foo", bar)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Errors in this attribute were erroneously allowed and will become a hard error in a future release.
+   = note: errors in this attribute were erroneously allowed and will become a hard error in a future release.
 
diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-panic-abort.rs
index b0679ea..b7bf5a1 100644
--- a/src/test/ui/test-panic-abort.rs
+++ b/src/test/ui/test-panic-abort.rs
@@ -11,6 +11,7 @@
 #![cfg(test)]
 
 use std::io::Write;
+use std::env;
 
 #[test]
 fn it_works() {
@@ -35,3 +36,13 @@
 fn it_exits() {
     std::process::exit(123);
 }
+
+#[test]
+fn no_residual_environment() {
+    for (key, _) in env::vars() {
+        // Look for keys like __RUST_TEST_INVOKE.
+        if key.contains("TEST_INVOKE") {
+            panic!("shouldn't have '{}' in environment", key);
+        }
+    }
+}
diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-panic-abort.run.stdout
index 0c8bc50..2f4bc32 100644
--- a/src/test/ui/test-panic-abort.run.stdout
+++ b/src/test/ui/test-panic-abort.run.stdout
@@ -1,9 +1,10 @@
 
-running 4 tests
+running 5 tests
 test it_exits ... FAILED
 test it_fails ... FAILED
 test it_panics ... ok
 test it_works ... ok
+test no_residual_environment ... ok
 
 failures:
 
@@ -17,13 +18,13 @@
 testing321
 thread 'main' panicked at 'assertion failed: `(left == right)`
   left: `2`,
- right: `5`', $DIR/test-panic-abort.rs:31:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
+ right: `5`', $DIR/test-panic-abort.rs:32:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 
 failures:
     it_exits
     it_fails
 
-test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
+test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
 
diff --git a/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs
index 44beb9d..2f6d35f 100644
--- a/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs
+++ b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs
@@ -88,6 +88,7 @@
     is_sync_send!((1..));
     is_sync_send!(repeat(1));
     is_sync_send!(empty::<usize>());
+    is_sync_send!(empty::<*mut i32>());
     is_sync_send!(once(1));
 
     // for option.rs
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 d5698be..bf45ba2 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
@@ -2,6 +2,7 @@
 type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip`
 
 #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+                   //~| ERROR cannot find derive macro `rustfmt` in this scope
 struct S;
 
 // Interpreted as an unstable custom attribute
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 b831e62..71fd5f1 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -4,14 +4,20 @@
 LL | #[derive(rustfmt)]
    |          ^^^^^^^
 
+error: cannot find derive macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:4:10
+   |
+LL | #[derive(rustfmt)]
+   |          ^^^^^^^
+
 error: cannot find attribute `rustfmt` in this scope
-  --> $DIR/tool-attributes-misplaced-1.rs:8:3
+  --> $DIR/tool-attributes-misplaced-1.rs:9:3
    |
 LL | #[rustfmt]
    |   ^^^^^^^
 
 error: cannot find macro `rustfmt` in this scope
-  --> $DIR/tool-attributes-misplaced-1.rs:14:5
+  --> $DIR/tool-attributes-misplaced-1.rs:15:5
    |
 LL |     rustfmt!();
    |     ^^^^^^^
@@ -29,18 +35,18 @@
    |          ^^^^^^^^^^^^^ not a type
 
 error[E0423]: expected value, found tool module `rustfmt`
-  --> $DIR/tool-attributes-misplaced-1.rs:13:5
+  --> $DIR/tool-attributes-misplaced-1.rs:14:5
    |
 LL |     rustfmt;
    |     ^^^^^^^ not a value
 
 error[E0423]: expected value, found tool attribute `rustfmt::skip`
-  --> $DIR/tool-attributes-misplaced-1.rs:16:5
+  --> $DIR/tool-attributes-misplaced-1.rs:17:5
    |
 LL |     rustfmt::skip;
    |     ^^^^^^^^^^^^^ not a value
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0423, E0573.
 For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs
index fa8f041..9c8540e 100644
--- a/src/test/ui/tool_lints.rs
+++ b/src/test/ui/tool_lints.rs
@@ -1,3 +1,5 @@
 #[warn(foo::bar)]
 //~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
+//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr
index de94160..86f8778 100644
--- a/src/test/ui/tool_lints.stderr
+++ b/src/test/ui/tool_lints.stderr
@@ -4,5 +4,17 @@
 LL | #[warn(foo::bar)]
    |        ^^^
 
-error: aborting due to previous error
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/tool_lints.rs:1:8
+   |
+LL | #[warn(foo::bar)]
+   |        ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/tool_lints.rs:1:8
+   |
+LL | #[warn(foo::bar)]
+   |        ^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/trailing-comma.rs b/src/test/ui/trailing-comma.rs
index 929c35a..97006ae 100644
--- a/src/test/ui/trailing-comma.rs
+++ b/src/test/ui/trailing-comma.rs
@@ -1,8 +1,6 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![feature(slice_patterns)]
-
 fn f<T,>(_: T,) {}
 
 struct Foo<T,>(T);
diff --git a/src/test/ui/traits/trait-bounds-same-crate-name.rs b/src/test/ui/traits/trait-bounds-same-crate-name.rs
index af720ec..1012edb 100644
--- a/src/test/ui/traits/trait-bounds-same-crate-name.rs
+++ b/src/test/ui/traits/trait-bounds-same-crate-name.rs
@@ -31,7 +31,7 @@
         a::try_foo(foo);
         //~^ ERROR E0277
         //~| trait impl with same name found
-        //~| Perhaps two different versions of crate `crate_a2`
+        //~| perhaps two different versions of crate `crate_a2`
 
         // We don't want to see the "version mismatch" help message here
         // because `implements_no_traits` has no impl for `Foo`
diff --git a/src/test/ui/traits/trait-bounds-same-crate-name.stderr b/src/test/ui/traits/trait-bounds-same-crate-name.stderr
index 8fd0bd1..8a6e059 100644
--- a/src/test/ui/traits/trait-bounds-same-crate-name.stderr
+++ b/src/test/ui/traits/trait-bounds-same-crate-name.stderr
@@ -14,7 +14,7 @@
    |
 LL | impl Bar for Foo {}
    | ^^^^^^^^^^^^^^^^^^^
-   = note: Perhaps two different versions of crate `crate_a2` are being used?
+   = note: perhaps two different versions of crate `crate_a2` are being used?
 
 error[E0277]: the trait bound `main::a::DoesNotImplementTrait: main::a::Bar` is not satisfied
   --> $DIR/trait-bounds-same-crate-name.rs:38:20
@@ -43,7 +43,7 @@
    |
 LL | impl Bar for ImplementsWrongTraitConditionally<isize> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: Perhaps two different versions of crate `crate_a2` are being used?
+   = note: perhaps two different versions of crate `crate_a2` are being used?
 
 error[E0277]: the trait bound `main::a::ImplementsTraitForUsize<isize>: main::a::Bar` is not satisfied
   --> $DIR/trait-bounds-same-crate-name.rs:51:20
diff --git a/src/test/ui/traits/trait-impl-1.rs b/src/test/ui/traits/trait-impl-1.rs
index 43b8222..d22ac72 100644
--- a/src/test/ui/traits/trait-impl-1.rs
+++ b/src/test/ui/traits/trait-impl-1.rs
@@ -12,5 +12,5 @@
 
 fn main() {
     let x = &42i32;
-    x.foo(); //~ERROR: no method named `foo` found for type `&i32` in the current scope
+    x.foo(); //~ERROR: no method named `foo` found
 }
diff --git a/src/test/ui/traits/trait-impl-1.stderr b/src/test/ui/traits/trait-impl-1.stderr
index 0d61c3e..da0936e 100644
--- a/src/test/ui/traits/trait-impl-1.stderr
+++ b/src/test/ui/traits/trait-impl-1.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for type `&i32` in the current scope
+error[E0599]: no method named `foo` found for reference `&i32` in the current scope
   --> $DIR/trait-impl-1.rs:15:7
    |
 LL |     x.foo();
diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs
index d58bbef38..8507d8e 100644
--- a/src/test/ui/traits/trait-item-privacy.rs
+++ b/src/test/ui/traits/trait-item-privacy.rs
@@ -64,8 +64,8 @@
 
     // Methods, method call
     // a, b, c are resolved as trait items, their traits need to be in scope
-    S.a(); //~ ERROR no method named `a` found for type `S` in the current scope
-    S.b(); //~ ERROR no method named `b` found for type `S` in the current scope
+    S.a(); //~ ERROR no method named `a` found
+    S.b(); //~ ERROR no method named `b` found
     S.c(); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     let c = &S as &dyn C;
@@ -76,9 +76,9 @@
     // Methods, UFCS
     // a, b, c are resolved as trait items, their traits need to be in scope
     S::a(&S);
-    //~^ ERROR no function or associated item named `a` found for type `S`
+    //~^ ERROR no function or associated item named `a` found
     S::b(&S);
-    //~^ ERROR no function or associated item named `b` found for type `S`
+    //~^ ERROR no function or associated item named `b` found
     S::c(&S); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     C::a(&S); //~ ERROR method `a` is private
@@ -94,8 +94,8 @@
 
     // Associated constants
     // A, B, C are resolved as trait items, their traits need to be in scope
-    S::A; //~ ERROR no associated item named `A` found for type `S` in the current scope
-    S::B; //~ ERROR no associated item named `B` found for type `S` in the current scope
+    S::A; //~ ERROR no associated item named `A` found
+    S::B; //~ ERROR no associated item named `B` found
     S::C; // OK
     // A, B, C are resolved as inherent items, their traits don't need to be in scope
     C::A; //~ ERROR associated constant `A` is private
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
index 64a92c6..4df8845 100644
--- a/src/test/ui/traits/trait-item-privacy.stderr
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `a` found for type `S` in the current scope
+error[E0599]: no method named `a` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:67:7
    |
 LL | struct S;
@@ -11,7 +11,7 @@
    = note: the following trait defines an item `a`, perhaps you need to implement it:
            candidate #1: `method::A`
 
-error[E0599]: no method named `b` found for type `S` in the current scope
+error[E0599]: no method named `b` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:68:7
    |
 LL | struct S;
@@ -39,7 +39,7 @@
 LL |     c.a();
    |       ^
 
-error[E0599]: no function or associated item named `a` found for type `S` in the current scope
+error[E0599]: no function or associated item named `a` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:78:8
    |
 LL | struct S;
@@ -52,7 +52,7 @@
    = note: the following trait defines an item `a`, perhaps you need to implement it:
            candidate #1: `method::A`
 
-error[E0599]: no function or associated item named `b` found for type `S` in the current scope
+error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:80:8
    |
 LL | struct S;
@@ -73,7 +73,7 @@
 LL |     C::a(&S);
    |     ^^^^
 
-error[E0599]: no associated item named `A` found for type `S` in the current scope
+error[E0599]: no associated item named `A` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:97:8
    |
 LL | struct S;
@@ -86,7 +86,7 @@
    = note: the following trait defines an item `A`, perhaps you need to implement it:
            candidate #1: `assoc_const::A`
 
-error[E0599]: no associated item named `B` found for type `S` in the current scope
+error[E0599]: no associated item named `B` found for struct `S` in the current scope
   --> $DIR/trait-item-privacy.rs:98:8
    |
 LL | struct S;
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs
index 6450ddd1..69eee66 100644
--- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs
@@ -1,4 +1,8 @@
-// run-pass
+// check-pass
+// compile-flags: --emit=mir,link
+// Force mir to be emitted, to ensure that const
+// propagation doesn't ICE on a function
+// with an 'impossible' body. See issue #67696
 // Inconsistent bounds with trait implementations
 
 #![feature(trivial_bounds)]
diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-on-option-diagnostics.rs
index 65d5e29..63d1741 100644
--- a/src/test/ui/try-on-option-diagnostics.rs
+++ b/src/test/ui/try-on-option-diagnostics.rs
@@ -16,3 +16,32 @@
     };
     a_closure()
 }
+
+fn a_method() -> u32 {
+    struct S;
+
+    impl S {
+        fn a_method() {
+            let x: Option<u32> = None;
+            x?; //~ ERROR the `?` operator
+        }
+    }
+
+    S::a_method();
+    22
+}
+
+fn a_trait_method() -> u32 {
+    struct S;
+    trait T {
+        fn a_trait_method() {
+            let x: Option<u32> = None;
+            x?; //~ ERROR the `?` operator
+        }
+    }
+
+    impl T for S { }
+
+    S::a_trait_method();
+    22
+}
diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr
index ce3aca3..c9dc3f1 100644
--- a/src/test/ui/try-on-option-diagnostics.stderr
+++ b/src/test/ui/try-on-option-diagnostics.stderr
@@ -27,6 +27,32 @@
    = help: the trait `std::ops::Try` is not implemented for `{integer}`
    = note: required by `std::ops::Try::from_error`
 
-error: aborting due to 2 previous errors
+error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-diagnostics.rs:26:13
+   |
+LL | /         fn a_method() {
+LL | |             let x: Option<u32> = None;
+LL | |             x?;
+   | |             ^^ cannot use the `?` operator in a method that returns `()`
+LL | |         }
+   | |_________- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::from_error`
+
+error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option-diagnostics.rs:39:13
+   |
+LL | /         fn a_trait_method() {
+LL | |             let x: Option<u32> = None;
+LL | |             x?;
+   | |             ^^ cannot use the `?` operator in a trait method that returns `()`
+LL | |         }
+   | |_________- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `std::ops::Try` is not implemented for `()`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.rs b/src/test/ui/tuple/tuple-struct-fields/test2.rs
index fc0f78b..2b2a2c1 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test2.rs
+++ b/src/test/ui/tuple/tuple-struct-fields/test2.rs
@@ -9,6 +9,7 @@
 
 mod foo {
     define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope
+                             //~| ERROR cannot find type `foo` in this scope
 }
 
 fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.stderr b/src/test/ui/tuple/tuple-struct-fields/test2.stderr
index d924c35..2f1ca2f 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test2.stderr
+++ b/src/test/ui/tuple/tuple-struct-fields/test2.stderr
@@ -15,6 +15,12 @@
 LL |     define_struct! { (foo) }
    |                       ^^^ not found in this scope
 
-error: aborting due to 2 previous errors
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test2.rs:11:23
+   |
+LL |     define_struct! { (foo) }
+   |                       ^^^ not found in this scope
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.rs b/src/test/ui/tuple/tuple-struct-fields/test3.rs
index 6b8534b..98d1942 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test3.rs
+++ b/src/test/ui/tuple/tuple-struct-fields/test3.rs
@@ -9,6 +9,7 @@
 
 mod foo {
     define_struct! { foo } //~ ERROR cannot find type `foo` in this scope
+                           //~| ERROR cannot find type `foo` in this scope
 }
 
 fn main() {}
diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.stderr b/src/test/ui/tuple/tuple-struct-fields/test3.stderr
index 50cac6c..5d42fe6 100644
--- a/src/test/ui/tuple/tuple-struct-fields/test3.stderr
+++ b/src/test/ui/tuple/tuple-struct-fields/test3.stderr
@@ -15,6 +15,12 @@
 LL |     define_struct! { foo }
    |                      ^^^ not found in this scope
 
-error: aborting due to 2 previous errors
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test3.rs:11:22
+   |
+LL |     define_struct! { foo }
+   |                      ^^^ not found in this scope
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
index dc41cbc..9549074 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
@@ -11,6 +11,9 @@
    |            ---   ^ expected `i32`, found opaque type
    |            |
    |            expected due to this
+...
+LL | type WrongGeneric<T> = impl 'static;
+   | ------------------------------------ the found opaque type
    |
    = note:     expected type `i32`
            found opaque type `WrongGeneric::<&{integer}>`
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index 24d23de..5a7f9d7 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -11,6 +11,9 @@
    |            ---   ^ expected `i32`, found opaque type
    |            |
    |            expected due to this
+...
+LL | type WrongGeneric<T> = impl 'static;
+   | ------------------------------------ the found opaque type
    |
    = note:     expected type `i32`
            found opaque type `WrongGeneric::<&{integer}>`
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index d4c7c7c..9e8414f 100644
--- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -18,6 +18,8 @@
 ...
 LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
    |                     - help: consider restricting this bound: `U: std::fmt::Debug`
+LL |     5u32
+   |     ---- this returned value is of type `u32`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `U`
    = note: the return type of a function must have a statically known size
@@ -30,6 +32,8 @@
 ...
 LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
    |                         - help: consider restricting this bound: `V: std::fmt::Debug`
+LL |     5u32
+   |     ---- this returned value is of type `u32`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `V`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
new file mode 100644
index 0000000..c46c471
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
@@ -0,0 +1,16 @@
+// Regression test for issue 67856
+
+#![feature(unboxed_closures)]
+#![feature(type_alias_impl_trait)]
+#![feature(fn_traits)]
+
+trait MyTrait {}
+impl MyTrait for () {}
+
+impl<F> FnOnce<()> for &F {
+    //~^ ERROR conflicting implementations
+    //~| ERROR type parameter `F` must be used
+    type Output = impl MyTrait;
+    extern "rust-call" fn call_once(self, _: ()) -> Self::Output {}
+}
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
new file mode 100644
index 0000000..f8e1e55
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
@@ -0,0 +1,23 @@
+error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_`:
+  --> $DIR/incoherent-assoc-imp-trait.rs:10:1
+   |
+LL | impl<F> FnOnce<()> for &F {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<A, F> std::ops::FnOnce<A> for &F
+             where F: std::ops::Fn<A>, F: ?Sized;
+
+error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`)
+  --> $DIR/incoherent-assoc-imp-trait.rs:10:6
+   |
+LL | impl<F> FnOnce<()> for &F {
+   |      ^ type parameter `F` must be used as the type parameter for some local type
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0210.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
new file mode 100644
index 0000000..1c2051e
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -0,0 +1,27 @@
+// Regression test for issue #57611
+// Ensures that we don't ICE
+// FIXME: This should compile, but it currently doesn't
+
+#![feature(trait_alias)]
+#![feature(type_alias_impl_trait)]
+
+trait Foo {
+    type Bar: Baz<Self, Self>;
+
+    fn bar(&self) -> Self::Bar;
+}
+
+struct X;
+
+impl Foo for X {
+    type Bar = impl Baz<Self, Self>; //~ ERROR type mismatch in closure arguments
+    //~^ ERROR type mismatch resolving
+
+    fn bar(&self) -> Self::Bar {
+        |x| x
+    }
+}
+
+trait Baz<A, B> = Fn(&A) -> &B;
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
new file mode 100644
index 0000000..f648b7b
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
@@ -0,0 +1,23 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-57611-trait-alias.rs:17:5
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _`
+...
+LL |         |x| x
+   |         ----- found signature of `fn(_) -> _`
+   |
+   = note: the return type of a function must have a statically known size
+
+error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X`
+  --> $DIR/issue-57611-trait-alias.rs:17:5
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
+   |
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs b/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs
new file mode 100644
index 0000000..fcab2c7
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57807-associated-type.rs
@@ -0,0 +1,31 @@
+// Regression test for issue #57807 - ensure
+// that we properly unify associated types within
+// a type alias impl trait
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+trait Bar {
+    type A;
+}
+
+impl Bar for () {
+    type A = ();
+}
+
+trait Foo {
+    type A;
+    type B: Bar<A = Self::A>;
+
+    fn foo() -> Self::B;
+}
+
+impl Foo for () {
+    type A = ();
+    type B = impl Bar<A = Self::A>;
+
+    fn foo() -> Self::B {
+        ()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-65918.rs b/src/test/ui/type-alias-impl-trait/issue-65918.rs
new file mode 100644
index 0000000..97efb85
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-65918.rs
@@ -0,0 +1,49 @@
+// build-pass
+
+#![feature(type_alias_impl_trait)]
+
+use std::marker::PhantomData;
+
+/* copied Index and TryFrom for convinience (and simplicity) */
+trait MyIndex<T> {
+    type O;
+    fn my_index(self) -> Self::O;
+}
+trait MyFrom<T>: Sized {
+    type Error;
+    fn my_from(value: T) -> Result<Self, Self::Error>;
+}
+
+/* MCVE starts here */
+trait F {}
+impl F for () {}
+type DummyT<T> = impl F;
+fn _dummy_t<T>() -> DummyT<T> {}
+
+struct Phantom1<T>(PhantomData<T>);
+struct Phantom2<T>(PhantomData<T>);
+struct Scope<T>(Phantom2<DummyT<T>>);
+
+impl<T> Scope<T> {
+    fn new() -> Self {
+        unimplemented!()
+    }
+}
+
+impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
+    type Error = ();
+    fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> {
+        unimplemented!()
+    }
+}
+
+impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> {
+    type O = T;
+    fn my_index(self) -> Self::O {
+        MyFrom::my_from(self.0).ok().unwrap()
+    }
+}
+
+fn main() {
+    let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
new file mode 100644
index 0000000..d00f8d7
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
@@ -0,0 +1,13 @@
+// Regression test for issue #68368
+// Ensures that we don't ICE when emitting an error
+// for a non-defining use when lifetimes are involved
+
+#![feature(type_alias_impl_trait)]
+trait Trait<T> {}
+type Alias<'a, U> = impl Trait<U>; //~ ERROR could not find defining uses
+fn f<'a>() -> Alias<'a, ()> {}
+//~^ ERROR defining opaque type use does not fully define opaque type: generic parameter `U`
+
+fn main() {}
+
+impl Trait<()> for () {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
new file mode 100644
index 0000000..b585942
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
@@ -0,0 +1,14 @@
+error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `()`
+  --> $DIR/issue-68368-non-defining-use.rs:8:1
+   |
+LL | fn f<'a>() -> Alias<'a, ()> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: could not find defining uses
+  --> $DIR/issue-68368-non-defining-use.rs:7:1
+   |
+LL | type Alias<'a, U> = impl Trait<U>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
index 07962e3..70c99c9 100644
--- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/never_reveal_concrete_type.rs:13:27
    |
+LL | type NoReveal = impl std::fmt::Debug;
+   | ------------------------------------- the found opaque type
+...
 LL |     let _: &'static str = x;
    |            ------------   ^ expected `&str`, found opaque type
    |            |
diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
index a208142..375c0bc 100644
--- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:15:19
    |
+LL |     pub type Boo = impl ::std::fmt::Debug;
+   |     -------------------------------------- the found opaque type
+...
 LL |     let _: &str = bomp();
    |            ----   ^^^^^^ expected `&str`, found opaque type
    |            |
@@ -12,6 +15,9 @@
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
    |
+LL |     pub type Boo = impl ::std::fmt::Debug;
+   |     -------------------------------------- the expected opaque type
+...
 LL | fn bomp() -> boo::Boo {
    |              -------- expected `Boo` because of return type
 LL |     ""
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
index 14c09ad..a656b20 100644
--- a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
+++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
@@ -4,7 +4,7 @@
 LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
    |                                       - possibly return type missing here?
 LL |     *x
-   |     ^^ expected `()`, found trait `std::iter::Iterator`
+   |     ^^ expected `()`, found trait object `dyn std::iter::Iterator`
    |
    = note: expected unit type `()`
            found trait object `(dyn std::iter::Iterator<Item = ()> + 'static)`
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs
index 5b0ca2f..86c7c52 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs
@@ -1,3 +1,4 @@
+#![feature(type_alias_impl_trait)] // Needed for single test `type Y = impl Trait<_>`
 // This test checks that it is not possible to enable global type
 // inference by using the `_` type placeholder.
 
@@ -42,6 +43,16 @@
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 
+fn test11(x: &usize) -> &_ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    &x
+}
+
+unsafe fn test12(x: *const usize) -> *const *const _ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    &x
+}
+
 impl Clone for Test9 {
     fn clone(&self) -> _ { Test9 }
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
@@ -57,6 +68,13 @@
 }
 
 pub fn main() {
+    static A = 42;
+    //~^ ERROR missing type for `static` item
+    static B: _ = 42;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    static C: Option<_> = Some(42);
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
     fn fn_test() -> _ { 5 }
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 
@@ -131,3 +149,37 @@
     fn assoc_fn_test3() -> _;
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
+
+struct BadStruct<_>(_);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+trait BadTrait<_> {}
+//~^ ERROR expected identifier, found reserved identifier `_`
+impl BadTrait<_> for BadStruct<_> {}
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn impl_trait() -> impl BadTrait<_> {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    unimplemented!()
+}
+
+struct BadStruct1<_, _>(_);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the name `_` is already used
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+struct BadStruct2<_, T>(_, T);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+
+type X = Box<_>;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+struct Struct;
+trait Trait<T> {}
+impl Trait<usize> for Struct {}
+type Y = impl Trait<_>;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+fn foo() -> Y {
+    Struct
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index 9fe7af4..f740a9f 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -1,5 +1,43 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:153:18
+   |
+LL | struct BadStruct<_>(_);
+   |                  ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:156:16
+   |
+LL | trait BadTrait<_> {}
+   |                ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:166:19
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                   ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:166:22
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                      ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:171:19
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                   ^ expected identifier, found reserved identifier
+
+error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/typeck_type_placeholder_item.rs:166:22
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                   -  ^ already used
+   |                   |
+   |                   first use of `_`
+
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:4:14
+  --> $DIR/typeck_type_placeholder_item.rs:5:14
    |
 LL | fn test() -> _ { 5 }
    |              ^
@@ -8,7 +46,7 @@
    |              help: replace with the correct return type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:7:16
+  --> $DIR/typeck_type_placeholder_item.rs:8:16
    |
 LL | fn test2() -> (_, _) { (5, 5) }
    |               -^--^-
@@ -18,7 +56,7 @@
    |               help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:10:15
+  --> $DIR/typeck_type_placeholder_item.rs:11:15
    |
 LL | static TEST3: _ = "test";
    |               ^
@@ -27,7 +65,7 @@
    |               help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:13:15
+  --> $DIR/typeck_type_placeholder_item.rs:14:15
    |
 LL | static TEST4: _ = 145;
    |               ^
@@ -36,13 +74,13 @@
    |               help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:16:15
+  --> $DIR/typeck_type_placeholder_item.rs:17:15
    |
 LL | static TEST5: (_, _) = (1, 2);
    |               ^^^^^^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:19:13
+  --> $DIR/typeck_type_placeholder_item.rs:20:13
    |
 LL | fn test6(_: _) { }
    |             ^ not allowed in type signatures
@@ -53,7 +91,7 @@
    |         ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:22:18
+  --> $DIR/typeck_type_placeholder_item.rs:23:18
    |
 LL | fn test6_b<T>(_: _, _: T) { }
    |                  ^ not allowed in type signatures
@@ -64,7 +102,7 @@
    |             ^^^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:25:30
+  --> $DIR/typeck_type_placeholder_item.rs:26:30
    |
 LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
    |                              ^ not allowed in type signatures
@@ -75,7 +113,7 @@
    |                         ^^^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:28:13
+  --> $DIR/typeck_type_placeholder_item.rs:29:13
    |
 LL | fn test7(x: _) { let _x: usize = x; }
    |             ^ not allowed in type signatures
@@ -86,13 +124,13 @@
    |         ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:31:22
+  --> $DIR/typeck_type_placeholder_item.rs:32:22
    |
 LL | fn test8(_f: fn() -> _) { }
    |                      ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:31:22
+  --> $DIR/typeck_type_placeholder_item.rs:32:22
    |
 LL | fn test8(_f: fn() -> _) { }
    |                      ^ not allowed in type signatures
@@ -103,7 +141,25 @@
    |         ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:54:8
+  --> $DIR/typeck_type_placeholder_item.rs:46:26
+   |
+LL | fn test11(x: &usize) -> &_ {
+   |                         -^
+   |                         ||
+   |                         |not allowed in type signatures
+   |                         help: replace with the correct return type: `&&usize`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:51:52
+   |
+LL | unsafe fn test12(x: *const usize) -> *const *const _ {
+   |                                      --------------^
+   |                                      |             |
+   |                                      |             not allowed in type signatures
+   |                                      help: replace with the correct return type: `*const *const usize`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:65:8
    |
 LL |     a: _,
    |        ^ not allowed in type signatures
@@ -121,8 +177,29 @@
 LL |     b: (T, T),
    |
 
+error: missing type for `static` item
+  --> $DIR/typeck_type_placeholder_item.rs:71:12
+   |
+LL |     static A = 42;
+   |            ^ help: provide a type for the item: `A: i32`
+
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:60:21
+  --> $DIR/typeck_type_placeholder_item.rs:73:15
+   |
+LL |     static B: _ = 42;
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `i32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:75:15
+   |
+LL |     static C: Option<_> = Some(42);
+   |               ^^^^^^^^^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:78:21
    |
 LL |     fn fn_test() -> _ { 5 }
    |                     ^
@@ -131,7 +208,7 @@
    |                     help: replace with the correct return type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:63:23
+  --> $DIR/typeck_type_placeholder_item.rs:81:23
    |
 LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      -^--^-
@@ -141,7 +218,7 @@
    |                      help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:66:22
+  --> $DIR/typeck_type_placeholder_item.rs:84:22
    |
 LL |     static FN_TEST3: _ = "test";
    |                      ^
@@ -150,7 +227,7 @@
    |                      help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:69:22
+  --> $DIR/typeck_type_placeholder_item.rs:87:22
    |
 LL |     static FN_TEST4: _ = 145;
    |                      ^
@@ -159,13 +236,13 @@
    |                      help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:72:22
+  --> $DIR/typeck_type_placeholder_item.rs:90:22
    |
 LL |     static FN_TEST5: (_, _) = (1, 2);
    |                      ^^^^^^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:75:20
+  --> $DIR/typeck_type_placeholder_item.rs:93:20
    |
 LL |     fn fn_test6(_: _) { }
    |                    ^ not allowed in type signatures
@@ -176,7 +253,7 @@
    |                ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:78:20
+  --> $DIR/typeck_type_placeholder_item.rs:96:20
    |
 LL |     fn fn_test7(x: _) { let _x: usize = x; }
    |                    ^ not allowed in type signatures
@@ -187,13 +264,13 @@
    |                ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:81:29
+  --> $DIR/typeck_type_placeholder_item.rs:99:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:81:29
+  --> $DIR/typeck_type_placeholder_item.rs:99:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
@@ -204,7 +281,7 @@
    |                ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:12
+  --> $DIR/typeck_type_placeholder_item.rs:122:12
    |
 LL |         a: _,
    |            ^ not allowed in type signatures
@@ -223,13 +300,13 @@
    |
 
 error[E0282]: type annotations needed
-  --> $DIR/typeck_type_placeholder_item.rs:109:27
+  --> $DIR/typeck_type_placeholder_item.rs:127:27
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                           ^^^^^^ cannot infer type
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:109:28
+  --> $DIR/typeck_type_placeholder_item.rs:127:28
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                            ^  ^ not allowed in type signatures
@@ -237,7 +314,7 @@
    |                            not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:113:30
+  --> $DIR/typeck_type_placeholder_item.rs:131:30
    |
 LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             -^--^-
@@ -247,7 +324,7 @@
    |                             help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:116:33
+  --> $DIR/typeck_type_placeholder_item.rs:134:33
    |
 LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           ------^-
@@ -256,7 +333,76 @@
    |                           help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:121:31
+  --> $DIR/typeck_type_placeholder_item.rs:153:21
+   |
+LL | struct BadStruct<_>(_);
+   |                     ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct<T>(T);
+   |                  ^  ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:158:15
+   |
+LL | impl BadTrait<_> for BadStruct<_> {}
+   |               ^                ^ not allowed in type signatures
+   |               |
+   |               not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | impl<T> BadTrait<T> for BadStruct<T> {}
+   |     ^^^          ^                ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:161:34
+   |
+LL | fn impl_trait() -> impl BadTrait<_> {
+   |                                  ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:166:25
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct1<T, _>(T);
+   |                   ^     ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:171:25
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct2<K, T>(K, T);
+   |                   ^     ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:175:14
+   |
+LL | type X = Box<_>;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:42:27
+   |
+LL |     fn test10(&self, _x : _) { }
+   |                           ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn test10<T>(&self, _x : T) { }
+   |              ^^^             ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:139:31
    |
 LL |     fn method_test1(&self, x: _);
    |                               ^ not allowed in type signatures
@@ -267,7 +413,7 @@
    |                    ^^^           ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:123:31
+  --> $DIR/typeck_type_placeholder_item.rs:141:31
    |
 LL |     fn method_test2(&self, x: _) -> _;
    |                               ^     ^ not allowed in type signatures
@@ -280,7 +426,7 @@
    |                    ^^^           ^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:125:31
+  --> $DIR/typeck_type_placeholder_item.rs:143:31
    |
 LL |     fn method_test3(&self) -> _;
    |                               ^ not allowed in type signatures
@@ -291,7 +437,7 @@
    |                    ^^^           ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:127:26
+  --> $DIR/typeck_type_placeholder_item.rs:145:26
    |
 LL |     fn assoc_fn_test1(x: _);
    |                          ^ not allowed in type signatures
@@ -302,7 +448,7 @@
    |                      ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:129:26
+  --> $DIR/typeck_type_placeholder_item.rs:147:26
    |
 LL |     fn assoc_fn_test2(x: _) -> _;
    |                          ^     ^ not allowed in type signatures
@@ -315,7 +461,7 @@
    |                      ^^^    ^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:131:28
+  --> $DIR/typeck_type_placeholder_item.rs:149:28
    |
 LL |     fn assoc_fn_test3() -> _;
    |                            ^ not allowed in type signatures
@@ -326,36 +472,7 @@
    |                      ^^^      ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:38:24
-   |
-LL |     fn test9(&self) -> _ { () }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `()`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:41:27
-   |
-LL |     fn test10(&self, _x : _) { }
-   |                           ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn test10<T>(&self, _x : T) { }
-   |              ^^^             ^
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:46:24
-   |
-LL |     fn clone(&self) -> _ { Test9 }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `Test9`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:49:37
+  --> $DIR/typeck_type_placeholder_item.rs:60:37
    |
 LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
    |                                     ^ not allowed in type signatures
@@ -366,16 +483,7 @@
    |                  ^^^                   ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:88:31
-   |
-LL |         fn fn_test9(&self) -> _ { () }
-   |                               ^
-   |                               |
-   |                               not allowed in type signatures
-   |                               help: replace with the correct return type: `()`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:91:34
+  --> $DIR/typeck_type_placeholder_item.rs:109:34
    |
 LL |         fn fn_test10(&self, _x : _) { }
    |                                  ^ not allowed in type signatures
@@ -386,16 +494,7 @@
    |                     ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:96:28
-   |
-LL |         fn clone(&self) -> _ { FnTest9 }
-   |                            ^
-   |                            |
-   |                            not allowed in type signatures
-   |                            help: replace with the correct return type: `main::FnTest9`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:99:41
+  --> $DIR/typeck_type_placeholder_item.rs:117:41
    |
 LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
    |                                         ^ not allowed in type signatures
@@ -405,7 +504,49 @@
 LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
    |                      ^^^                   ^
 
-error: aborting due to 40 previous errors
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:181:21
+   |
+LL | type Y = impl Trait<_>;
+   |                     ^ not allowed in type signatures
 
-Some errors have detailed explanations: E0121, E0282.
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:39:24
+   |
+LL |     fn test9(&self) -> _ { () }
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `()`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:57:24
+   |
+LL |     fn clone(&self) -> _ { Test9 }
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `Test9`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:106:31
+   |
+LL |         fn fn_test9(&self) -> _ { () }
+   |                               ^
+   |                               |
+   |                               not allowed in type signatures
+   |                               help: replace with the correct return type: `()`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:114:28
+   |
+LL |         fn clone(&self) -> _ { FnTest9 }
+   |                            ^
+   |                            |
+   |                            not allowed in type signatures
+   |                            help: replace with the correct return type: `main::FnTest9`
+
+error: aborting due to 58 previous errors
+
+Some errors have detailed explanations: E0121, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
index 82a593f..66d4db3 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.rs
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -35,7 +35,7 @@
     <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
     let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
     let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
-    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y`
+    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found
     <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
 
     let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
@@ -52,5 +52,5 @@
     let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
     let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
-    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X`
+    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found
 }
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index dbd41da..60ebe8e 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -207,13 +207,13 @@
 LL |     let _: <u8 as Tr>::Y::NN;
    |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
 
-error[E0599]: no associated item named `NN` found for type `<u8 as Tr>::Y` in the current scope
+error[E0599]: no associated item named `NN` found for associated type `<u8 as Tr>::Y` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:38:20
    |
 LL |     <u8 as Tr>::Y::NN;
    |                    ^^ associated item not found in `<u8 as Tr>::Y`
 
-error[E0599]: no associated item named `N` found for type `<u8 as Dr>::X` in the current scope
+error[E0599]: no associated item named `N` found for associated type `<u8 as Dr>::X` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:55:20
    |
 LL |     <u8 as Dr>::X::N;
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
index 9fb9a07..0a028e4 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
@@ -2,9 +2,18 @@
   --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39
    |
 LL |     let _: dyn Foo(&isize, &usize) -> &usize;
-   |                                       ^ expected lifetime parameter
+   |                                       ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+help: consider introducing a named lifetime parameter
+   |
+LL | fn main<'lifetime>() {
+LL |     eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>,
+LL |           dyn Foo(&isize) -> &isize                                   >();
+LL |     eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
+LL |           dyn Foo(&isize) -> (&isize, &isize)                           >();
+LL | 
+ ...
 
 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 18276d5..0b6d94e 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
@@ -1,10 +1,10 @@
-error[E0599]: no method named `call` found for type `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
    |          ^^^^ 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
+   = note: `mut_` is a function, perhaps you wish to call it
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr
index 44cfc5c..2983613 100644
--- a/src/test/ui/underscore-imports/hygiene.stderr
+++ b/src/test/ui/underscore-imports/hygiene.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `deref` found for type `&()` in the current scope
+error[E0599]: no method named `deref` found for reference `&()` in the current scope
   --> $DIR/hygiene.rs:38:11
    |
 LL |     (&()).deref();
@@ -10,7 +10,7 @@
 LL | use std::ops::Deref;
    |
 
-error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope
+error[E0599]: no method named `deref_mut` found for mutable reference `&mut ()` in the current scope
   --> $DIR/hygiene.rs:39:15
    |
 LL |     (&mut ()).deref_mut();
diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr
index 102c17f..eb16fa9 100644
--- a/src/test/ui/underscore-imports/shadow.stderr
+++ b/src/test/ui/underscore-imports/shadow.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `deref` found for type `&()` in the current scope
+error[E0599]: no method named `deref` found for reference `&()` in the current scope
   --> $DIR/shadow.rs:19:11
    |
 LL |         x.deref();
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
index b20c23a..04df2e4 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
@@ -2,7 +2,13 @@
   --> $DIR/dyn-trait-underscore-in-struct.rs:9:24
    |
 LL |     x: Box<dyn Debug + '_>,
-   |                        ^^ expected lifetime parameter
+   |                        ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Foo<'lifetime> {
+LL |     x: Box<dyn Debug + 'lifetime>,
+   |
 
 error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
   --> $DIR/dyn-trait-underscore-in-struct.rs:9:12
diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
index ed61bdf..cf82024 100644
--- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
+++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
@@ -2,9 +2,13 @@
   --> $DIR/in-fn-return-illegal.rs:5:30
    |
 LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
-   |                              ^^ expected lifetime parameter
+   |                              ^^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo<'lifetime>(x: &u32, y: &u32) -> &'lifetime u32 { loop { } }
+   |       ^^^^^^^^^^^                       ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/in-struct.stderr b/src/test/ui/underscore-lifetime/in-struct.stderr
index 6bbdc71..e01b39a 100644
--- a/src/test/ui/underscore-lifetime/in-struct.stderr
+++ b/src/test/ui/underscore-lifetime/in-struct.stderr
@@ -2,13 +2,25 @@
   --> $DIR/in-struct.rs:6:9
    |
 LL |     x: &'_ u32,
-   |         ^^ expected lifetime parameter
+   |         ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | struct Foo<'lifetime> {
+LL |     x: &'lifetime u32,
+   |
 
 error[E0106]: missing lifetime specifier
   --> $DIR/in-struct.rs:10:14
    |
 LL |     Variant(&'_ u32),
-   |              ^^ expected lifetime parameter
+   |              ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | enum Bar<'lifetime> {
+LL |     Variant(&'lifetime u32),
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
index ef9e7e3..517904e 100644
--- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
@@ -14,7 +14,7 @@
   --> $DIR/underscore-lifetime-binders.rs:2:17
    |
 LL | struct Baz<'a>(&'_ &'a u8);
-   |                 ^^ expected lifetime parameter
+   |                 ^^ help: consider using the named lifetime: `'a`
 
 error[E0106]: missing lifetime specifier
   --> $DIR/underscore-lifetime-binders.rs:10:33
@@ -28,9 +28,13 @@
   --> $DIR/underscore-lifetime-binders.rs:16:35
    |
 LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
-   |                                   ^^ expected lifetime parameter
+   |                                   ^^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y`
+help: consider introducing a named lifetime parameter
+   |
+LL | fn foo2<'lifetime>(_: &'_ u8, y: &'_ u8) -> &'lifetime u8 { y }
+   |        ^^^^^^^^^^^                           ^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/uninhabited/uninhabited-patterns.rs b/src/test/ui/uninhabited/uninhabited-patterns.rs
index 1bf0118..58c726d 100644
--- a/src/test/ui/uninhabited/uninhabited-patterns.rs
+++ b/src/test/ui/uninhabited/uninhabited-patterns.rs
@@ -2,7 +2,7 @@
 #![feature(box_syntax)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
-#![feature(slice_patterns)]
+
 #![deny(unreachable_patterns)]
 
 mod foo {
diff --git a/src/test/ui/union/union-const-pat.rs b/src/test/ui/union/union-const-pat.rs
index e7cb248..cb2248c 100644
--- a/src/test/ui/union/union-const-pat.rs
+++ b/src/test/ui/union/union-const-pat.rs
@@ -8,6 +8,7 @@
 fn main() {
     match C {
         C => {} //~ ERROR cannot use unions in constant patterns
+                //~| ERROR cannot use unions in constant patterns
         _ => {}
     }
 }
diff --git a/src/test/ui/union/union-const-pat.stderr b/src/test/ui/union/union-const-pat.stderr
index dc87f4d..bec7204 100644
--- a/src/test/ui/union/union-const-pat.stderr
+++ b/src/test/ui/union/union-const-pat.stderr
@@ -4,5 +4,11 @@
 LL |         C => {}
    |         ^
 
-error: aborting due to previous error
+error: cannot use unions in constant patterns
+  --> $DIR/union-const-pat.rs:10:9
+   |
+LL |         C => {}
+   |         ^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs
index 60e280f..4a106cc 100644
--- a/src/test/ui/union/union-derive-clone.rs
+++ b/src/test/ui/union/union-derive-clone.rs
@@ -34,5 +34,5 @@
 
 fn main() {
     let u = U5 { a: ManuallyDrop::new(CloneNoCopy) };
-    let w = u.clone(); //~ ERROR no method named `clone` found for type `U5<CloneNoCopy>`
+    let w = u.clone(); //~ ERROR no method named `clone` found for union `U5<CloneNoCopy>`
 }
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index 6893f91..0ef5753 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -6,7 +6,7 @@
    |
    = note: required by `std::clone::AssertParamIsCopy`
 
-error[E0599]: no method named `clone` found for type `U5<CloneNoCopy>` in the current scope
+error[E0599]: no method named `clone` found for union `U5<CloneNoCopy>` in the current scope
   --> $DIR/union-derive-clone.rs:37:15
    |
 LL | union U5<T> {
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index cd46878..92cda64 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `std::boxed::Box<dyn Foo>` in the current scope
+error[E0599]: no method named `clone` found for struct `std::boxed::Box<dyn Foo>` in the current scope
   --> $DIR/unique-object-noncopyable.rs:24:16
    |
 LL |     let _z = y.clone();
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index 19ef2b2..e5c3eac 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `clone` found for type `std::boxed::Box<R>` in the current scope
+error[E0599]: no method named `clone` found for struct `std::boxed::Box<R>` in the current scope
   --> $DIR/unique-pinned-nocopy.rs:12:16
    |
 LL |     let _j = i.clone();
diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs
index c92a71e..182aec3 100644
--- a/src/test/ui/unknown-lint-tool-name.rs
+++ b/src/test/ui/unknown-lint-tool-name.rs
@@ -1,4 +1,8 @@
 #![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
 
 #[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr
index dd3070b..1940f61 100644
--- a/src/test/ui/unknown-lint-tool-name.stderr
+++ b/src/test/ui/unknown-lint-tool-name.stderr
@@ -5,10 +5,34 @@
    |         ^^^
 
 error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
-  --> $DIR/unknown-lint-tool-name.rs:3:9
+  --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
 
-error: aborting due to 2 previous errors
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:1:9
+   |
+LL | #![deny(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:5:9
+   |
+LL | #[allow(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:1:9
+   |
+LL | #![deny(foo::bar)]
+   |         ^^^
+
+error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+  --> $DIR/unknown-lint-tool-name.rs:5:9
+   |
+LL | #[allow(foo::bar)]
+   |         ^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr
index b72d45e..e057a78 100644
--- a/src/test/ui/unspecified-self-in-trait-ref.stderr
+++ b/src/test/ui/unspecified-self-in-trait-ref.stderr
@@ -1,22 +1,22 @@
-error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:10:18
    |
 LL |     let a = Foo::lol();
    |                  ^^^ function or associated item not found in `dyn Foo<_>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:12:23
    |
 LL |     let b = Foo::<_>::lol();
    |                       ^^^ function or associated item not found in `dyn Foo<_>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Bar<_, _>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<_, _>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:14:18
    |
 LL |     let c = Bar::lol();
    |                  ^^^ function or associated item not found in `dyn Bar<_, _>`
 
-error[E0599]: no function or associated item named `lol` found for type `dyn Bar<usize, _>` in the current scope
+error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<usize, _>` in the current scope
   --> $DIR/unspecified-self-in-trait-ref.rs:16:30
    |
 LL |     let d = Bar::<usize, _>::lol();
diff --git a/src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs b/src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs
new file mode 100644
index 0000000..3c7756e
--- /dev/null
+++ b/src/test/ui/use/auxiliary/extern-use-primitive-type-lib.rs
@@ -0,0 +1,3 @@
+// compile-flags: --edition=2018
+
+pub use u32;
diff --git a/src/test/ui/use/issue-60976-extern-use-primitive-type.rs b/src/test/ui/use/issue-60976-extern-use-primitive-type.rs
new file mode 100644
index 0000000..4cd4583
--- /dev/null
+++ b/src/test/ui/use/issue-60976-extern-use-primitive-type.rs
@@ -0,0 +1,7 @@
+// Regression test for #60976: ICE (with <=1.36.0) when another file had `use <primitive_type>;`.
+// check-pass
+// aux-build:extern-use-primitive-type-lib.rs
+
+extern crate extern_use_primitive_type_lib;
+
+fn main() {}
diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr
index f7438cc..3f38a6c 100644
--- a/src/test/ui/use/use-from-trait-xc.stderr
+++ b/src/test/ui/use/use-from-trait-xc.stderr
@@ -44,13 +44,25 @@
   --> $DIR/use-from-trait-xc.rs:14:24
    |
 LL | use use_from_trait_xc::Foo::new;
-   |                        ^^^
+   |                        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/auxiliary/use-from-trait-xc.rs:9:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
 
 error[E0603]: struct `Foo` is private
   --> $DIR/use-from-trait-xc.rs:17:24
    |
 LL | use use_from_trait_xc::Foo::C;
-   |                        ^^^
+   |                        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/auxiliary/use-from-trait-xc.rs:9:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/use/use-mod/use-mod-3.stderr b/src/test/ui/use/use-mod/use-mod-3.stderr
index 0c800ec..4852759 100644
--- a/src/test/ui/use/use-mod/use-mod-3.stderr
+++ b/src/test/ui/use/use-mod/use-mod-3.stderr
@@ -2,13 +2,25 @@
   --> $DIR/use-mod-3.rs:1:10
    |
 LL | use foo::bar::{
-   |          ^^^
+   |          ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/use-mod-3.rs:9:5
+   |
+LL |     mod bar { pub type Bar = isize; }
+   |     ^^^^^^^
 
 error[E0603]: module `bar` is private
   --> $DIR/use-mod-3.rs:4:10
    |
 LL | use foo::bar::{
-   |          ^^^
+   |          ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/use-mod-3.rs:9:5
+   |
+LL |     mod bar { pub type Bar = isize; }
+   |     ^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/use/use-super-global-path.rs b/src/test/ui/use/use-super-global-path.rs
index 3e0ebcc..27a4a65 100644
--- a/src/test/ui/use/use-super-global-path.rs
+++ b/src/test/ui/use/use-super-global-path.rs
@@ -5,6 +5,7 @@
 
 mod foo {
     use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
+                         //~| ERROR global paths cannot start with `super`
 
     pub fn g() {
         use ::super::main; //~ ERROR global paths cannot start with `super`
diff --git a/src/test/ui/use/use-super-global-path.stderr b/src/test/ui/use/use-super-global-path.stderr
index 3ca30eb..7f98ac7 100644
--- a/src/test/ui/use/use-super-global-path.stderr
+++ b/src/test/ui/use/use-super-global-path.stderr
@@ -5,13 +5,19 @@
    |           ^^^^^ global paths cannot start with `super`
 
 error[E0433]: failed to resolve: global paths cannot start with `super`
-  --> $DIR/use-super-global-path.rs:10:15
+  --> $DIR/use-super-global-path.rs:7:11
+   |
+LL |     use ::super::{S, Z};
+   |           ^^^^^ global paths cannot start with `super`
+
+error[E0433]: failed to resolve: global paths cannot start with `super`
+  --> $DIR/use-super-global-path.rs:11:15
    |
 LL |         use ::super::main;
    |               ^^^^^ global paths cannot start with `super`
 
 error[E0425]: cannot find function `main` in this scope
-  --> $DIR/use-super-global-path.rs:11:9
+  --> $DIR/use-super-global-path.rs:12:9
    |
 LL |         main();
    |         ^^^^ not found in this scope
@@ -21,7 +27,7 @@
 LL |     use main;
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0425, E0433.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.stderr b/src/test/ui/where-clauses/where-lifetime-resolution.stderr
index 0081ae0..49799a9 100644
--- a/src/test/ui/where-clauses/where-lifetime-resolution.stderr
+++ b/src/test/ui/where-clauses/where-lifetime-resolution.stderr
@@ -1,6 +1,9 @@
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/where-lifetime-resolution.rs:6:38
    |
+LL | fn f() where
+   |     - help: consider introducing lifetime `'a` here: `<'a>`
+LL |     for<'a> dyn Trait1<'a>: Trait1<'a>, // OK
 LL |     (dyn for<'a> Trait1<'a>): Trait1<'a>,
    |                                      ^^ undeclared lifetime
 
@@ -13,6 +16,9 @@
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/where-lifetime-resolution.rs:8:52
    |
+LL | fn f() where
+   |     - help: consider introducing lifetime `'b` here: `<'b>`
+...
 LL |     for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
    |                                                    ^^ undeclared lifetime
 
diff --git a/src/test/ui/xcrate/xcrate-private-by-default.stderr b/src/test/ui/xcrate/xcrate-private-by-default.stderr
index da52b42..842069d 100644
--- a/src/test/ui/xcrate/xcrate-private-by-default.stderr
+++ b/src/test/ui/xcrate/xcrate-private-by-default.stderr
@@ -2,61 +2,121 @@
   --> $DIR/xcrate-private-by-default.rs:23:29
    |
 LL |     static_priv_by_default::j;
-   |                             ^
+   |                             ^ this static is private
+   |
+note: the static `j` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:47:1
+   |
+LL | static j: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: function `k` is private
   --> $DIR/xcrate-private-by-default.rs:25:29
    |
 LL |     static_priv_by_default::k;
-   |                             ^
+   |                             ^ this function is private
+   |
+note: the function `k` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:48:1
+   |
+LL | fn k() {}
+   | ^^^^^^
 
 error[E0603]: unit struct `l` is private
   --> $DIR/xcrate-private-by-default.rs:27:29
    |
 LL |     static_priv_by_default::l;
-   |                             ^
+   |                             ^ this unit struct is private
+   |
+note: the unit struct `l` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:49:1
+   |
+LL | struct l;
+   | ^^^^^^^^^
 
 error[E0603]: enum `m` is private
   --> $DIR/xcrate-private-by-default.rs:29:35
    |
 LL |     foo::<static_priv_by_default::m>();
-   |                                   ^
+   |                                   ^ this enum is private
+   |
+note: the enum `m` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:50:1
+   |
+LL | enum m {}
+   | ^^^^^^
 
 error[E0603]: type alias `n` is private
   --> $DIR/xcrate-private-by-default.rs:31:35
    |
 LL |     foo::<static_priv_by_default::n>();
-   |                                   ^
+   |                                   ^ this type alias is private
+   |
+note: the type alias `n` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:51:1
+   |
+LL | type n = isize;
+   | ^^^^^^^^^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:35:29
    |
 LL |     static_priv_by_default::foo::a;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:37:29
    |
 LL |     static_priv_by_default::foo::b;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:39:29
    |
 LL |     static_priv_by_default::foo::c;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:41:35
    |
 LL |     foo::<static_priv_by_default::foo::d>();
-   |                                   ^^^
+   |                                   ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:43:35
    |
 LL |     foo::<static_priv_by_default::foo::e>();
-   |                                   ^^^
+   |                                   ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error: aborting due to 10 previous errors
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 481163a..98e9fe7 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -69,6 +69,7 @@
     "thumbv7neon-linux-androideabi",
     "armv7-unknown-linux-gnueabi",
     "armv7-unknown-linux-gnueabihf",
+    "armv7a-none-eabi",
     "thumbv7neon-unknown-linux-gnueabihf",
     "armv7-unknown-linux-musleabi",
     "armv7-unknown-linux-musleabihf",
@@ -110,6 +111,7 @@
     "riscv32imac-unknown-none-elf",
     "riscv64imac-unknown-none-elf",
     "riscv64gc-unknown-none-elf",
+    "riscv64gc-unknown-linux-gnu",
     "s390x-unknown-linux-gnu",
     "sparc64-unknown-linux-gnu",
     "sparcv9-sun-solaris",
diff --git a/src/tools/cargo b/src/tools/cargo
index 6e1ca92..f6449ba 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 6e1ca924a67dd1ac89c33f294ef26b5c43b89168
+Subproject commit f6449ba236db31995255ac5e4cad4ab88296a7c6
diff --git a/src/tools/clippy b/src/tools/clippy
index e8642c7..3e74853 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit e8642c7a2900bed28003a98d4db8b62290ac802f
+Subproject commit 3e74853d1f9893cf2a47f28b658711d8f9f97b6b
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 80ef8dd..a26c3a4 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -12,7 +12,7 @@
 regex = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
-rustfix = "0.4.1"
+rustfix = "0.5.0"
 lazy_static = "1.0"
 walkdir = "2"
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 01001ff..9cc1906 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -14,10 +14,7 @@
     RunFail,
     RunPassValgrind,
     Pretty,
-    DebugInfoCdb,
-    DebugInfoGdbLldb,
-    DebugInfoGdb,
-    DebugInfoLldb,
+    DebugInfo,
     Codegen,
     Rustdoc,
     CodegenUnits,
@@ -32,13 +29,9 @@
 impl Mode {
     pub fn disambiguator(self) -> &'static str {
         // Pretty-printing tests could run concurrently, and if they do,
-        // they need to keep their output segregated. Same is true for debuginfo tests that
-        // can be run on cdb, gdb, and lldb.
+        // they need to keep their output segregated.
         match self {
             Pretty => ".pretty",
-            DebugInfoCdb => ".cdb",
-            DebugInfoGdb => ".gdb",
-            DebugInfoLldb => ".lldb",
             _ => "",
         }
     }
@@ -52,10 +45,7 @@
             "run-fail" => Ok(RunFail),
             "run-pass-valgrind" => Ok(RunPassValgrind),
             "pretty" => Ok(Pretty),
-            "debuginfo-cdb" => Ok(DebugInfoCdb),
-            "debuginfo-gdb+lldb" => Ok(DebugInfoGdbLldb),
-            "debuginfo-lldb" => Ok(DebugInfoLldb),
-            "debuginfo-gdb" => Ok(DebugInfoGdb),
+            "debuginfo" => Ok(DebugInfo),
             "codegen" => Ok(Codegen),
             "rustdoc" => Ok(Rustdoc),
             "codegen-units" => Ok(CodegenUnits),
@@ -77,10 +67,7 @@
             RunFail => "run-fail",
             RunPassValgrind => "run-pass-valgrind",
             Pretty => "pretty",
-            DebugInfoCdb => "debuginfo-cdb",
-            DebugInfoGdbLldb => "debuginfo-gdb+lldb",
-            DebugInfoGdb => "debuginfo-gdb",
-            DebugInfoLldb => "debuginfo-lldb",
+            DebugInfo => "debuginfo",
             Codegen => "codegen",
             Rustdoc => "rustdoc",
             CodegenUnits => "codegen-units",
@@ -155,6 +142,29 @@
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum Debugger {
+    Cdb,
+    Gdb,
+    Lldb,
+}
+
+impl Debugger {
+    fn to_str(&self) -> &'static str {
+        match self {
+            Debugger::Cdb => "cdb",
+            Debugger::Gdb => "gdb",
+            Debugger::Lldb => "lldb",
+        }
+    }
+}
+
+impl fmt::Display for Debugger {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.to_str(), f)
+    }
+}
+
 /// Configuration for compiletest
 #[derive(Clone)]
 pub struct Config {
@@ -208,6 +218,9 @@
     /// The test mode, compile-fail, run-fail, ui
     pub mode: Mode,
 
+    /// The debugger to use in debuginfo mode. Unset otherwise.
+    pub debugger: Option<Debugger>,
+
     /// Run ignored tests
     pub run_ignored: bool,
 
@@ -362,9 +375,11 @@
     revision: Option<&str>,
 ) -> PathBuf {
     let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str());
+    let debugger = config.debugger.as_ref().map_or("", |m| m.to_str());
     PathBuf::from(&testpaths.file.file_stem().unwrap())
         .with_extra_extension(revision.unwrap_or(""))
         .with_extra_extension(mode)
+        .with_extra_extension(debugger)
 }
 
 /// Absolute path to the directory where all output for the given
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 691b8d3..34f9ac0 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,52 +6,13 @@
 
 use log::*;
 
-use crate::common::{self, CompareMode, Config, FailMode, Mode, PassMode};
+use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode};
 use crate::extract_gdb_version;
 use crate::util;
 
 #[cfg(test)]
 mod tests;
 
-/// Whether to ignore the test.
-#[derive(Clone, Copy, PartialEq, Debug)]
-pub enum Ignore {
-    /// Runs it.
-    Run,
-    /// Ignore it totally.
-    Ignore,
-    /// Ignore only the gdb test, but run the lldb test.
-    IgnoreGdb,
-    /// Ignore only the lldb test, but run the gdb test.
-    IgnoreLldb,
-}
-
-impl Ignore {
-    pub fn can_run_gdb(&self) -> bool {
-        *self == Ignore::Run || *self == Ignore::IgnoreLldb
-    }
-
-    pub fn can_run_lldb(&self) -> bool {
-        *self == Ignore::Run || *self == Ignore::IgnoreGdb
-    }
-
-    pub fn no_gdb(&self) -> Ignore {
-        match *self {
-            Ignore::Run => Ignore::IgnoreGdb,
-            Ignore::IgnoreGdb => Ignore::IgnoreGdb,
-            _ => Ignore::Ignore,
-        }
-    }
-
-    pub fn no_lldb(&self) -> Ignore {
-        match *self {
-            Ignore::Run => Ignore::IgnoreLldb,
-            Ignore::IgnoreLldb => Ignore::IgnoreLldb,
-            _ => Ignore::Ignore,
-        }
-    }
-}
-
 /// The result of parse_cfg_name_directive.
 #[derive(Clone, Copy, PartialEq, Debug)]
 enum ParsedNameDirective {
@@ -59,16 +20,12 @@
     NoMatch,
     /// Match.
     Match,
-    /// Mode was DebugInfoGdbLldb and this matched gdb.
-    MatchGdb,
-    /// Mode was DebugInfoGdbLldb and this matched lldb.
-    MatchLldb,
 }
 
 /// Properties which must be known very early, before actually running
 /// the test.
 pub struct EarlyProps {
-    pub ignore: Ignore,
+    pub ignore: bool,
     pub should_fail: bool,
     pub aux: Vec<String>,
     pub aux_crate: Vec<(String, String)>,
@@ -78,84 +35,61 @@
 impl EarlyProps {
     pub fn from_file(config: &Config, testfile: &Path) -> Self {
         let mut props = EarlyProps {
-            ignore: Ignore::Run,
+            ignore: false,
             should_fail: false,
             aux: Vec::new(),
             aux_crate: Vec::new(),
             revisions: vec![],
         };
 
-        if config.mode == common::DebugInfoGdbLldb {
-            if config.lldb_python_dir.is_none() {
-                props.ignore = props.ignore.no_lldb();
-            }
-            if config.gdb_version.is_none() {
-                props.ignore = props.ignore.no_gdb();
-            }
-        } else if config.mode == common::DebugInfoCdb {
-            if config.cdb.is_none() {
-                props.ignore = Ignore::Ignore;
-            }
-        }
-
         let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
         let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
 
         iter_header(testfile, None, &mut |ln| {
             // we should check if any only-<platform> exists and if it exists
             // and does not matches the current platform, skip the test
-            if props.ignore != Ignore::Ignore {
+            if !props.ignore {
                 props.ignore = match config.parse_cfg_name_directive(ln, "ignore") {
-                    ParsedNameDirective::Match => Ignore::Ignore,
+                    ParsedNameDirective::Match => true,
                     ParsedNameDirective::NoMatch => props.ignore,
-                    ParsedNameDirective::MatchGdb => props.ignore.no_gdb(),
-                    ParsedNameDirective::MatchLldb => props.ignore.no_lldb(),
                 };
 
                 if config.has_cfg_prefix(ln, "only") {
                     props.ignore = match config.parse_cfg_name_directive(ln, "only") {
                         ParsedNameDirective::Match => props.ignore,
-                        ParsedNameDirective::NoMatch => Ignore::Ignore,
-                        ParsedNameDirective::MatchLldb => props.ignore.no_gdb(),
-                        ParsedNameDirective::MatchGdb => props.ignore.no_lldb(),
+                        ParsedNameDirective::NoMatch => true,
                     };
                 }
 
                 if ignore_llvm(config, ln) {
-                    props.ignore = Ignore::Ignore;
+                    props.ignore = true;
                 }
 
                 if config.run_clang_based_tests_with.is_none()
                     && config.parse_needs_matching_clang(ln)
                 {
-                    props.ignore = Ignore::Ignore;
+                    props.ignore = true;
                 }
 
                 if !rustc_has_profiler_support && config.parse_needs_profiler_support(ln) {
-                    props.ignore = Ignore::Ignore;
+                    props.ignore = true;
                 }
 
                 if !rustc_has_sanitizer_support && config.parse_needs_sanitizer_support(ln) {
-                    props.ignore = Ignore::Ignore;
+                    props.ignore = true;
                 }
 
                 if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) {
-                    props.ignore = Ignore::Ignore;
+                    props.ignore = true;
                 }
-            }
 
-            if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb)
-                && props.ignore.can_run_gdb()
-                && ignore_gdb(config, ln)
-            {
-                props.ignore = props.ignore.no_gdb();
-            }
+                if config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln) {
+                    props.ignore = true;
+                }
 
-            if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoGdbLldb)
-                && props.ignore.can_run_lldb()
-                && ignore_lldb(config, ln)
-            {
-                props.ignore = props.ignore.no_lldb();
+                if config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln) {
+                    props.ignore = true;
+                }
             }
 
             if let Some(s) = config.parse_aux_build(ln) {
@@ -881,70 +815,37 @@
     /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
     /// or `normalize-stderr-32bit`.
     fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective {
-        if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') {
-            let name = line[prefix.len() + 1..].split(&[':', ' '][..]).next().unwrap();
-
-            if name == "test" ||
-                &self.target == name ||                             // triple
-                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
-                (self.target != self.host && name == "cross-compile") ||
-                match self.compare_mode {
-                    Some(CompareMode::Nll) => name == "compare-mode-nll",
-                    Some(CompareMode::Polonius) => name == "compare-mode-polonius",
-                    None => false,
-                } ||
-                (cfg!(debug_assertions) && name == "debug")
-            {
-                ParsedNameDirective::Match
-            } else {
-                match self.mode {
-                    common::DebugInfoGdbLldb => {
-                        if name == "gdb" {
-                            ParsedNameDirective::MatchGdb
-                        } else if name == "lldb" {
-                            ParsedNameDirective::MatchLldb
-                        } else {
-                            ParsedNameDirective::NoMatch
-                        }
-                    }
-                    common::DebugInfoCdb => {
-                        if name == "cdb" {
-                            ParsedNameDirective::Match
-                        } else {
-                            ParsedNameDirective::NoMatch
-                        }
-                    }
-                    common::DebugInfoGdb => {
-                        if name == "gdb" {
-                            ParsedNameDirective::Match
-                        } else {
-                            ParsedNameDirective::NoMatch
-                        }
-                    }
-                    common::DebugInfoLldb => {
-                        if name == "lldb" {
-                            ParsedNameDirective::Match
-                        } else {
-                            ParsedNameDirective::NoMatch
-                        }
-                    }
-                    common::Pretty => {
-                        if name == "pretty" {
-                            ParsedNameDirective::Match
-                        } else {
-                            ParsedNameDirective::NoMatch
-                        }
-                    }
-                    _ => ParsedNameDirective::NoMatch,
-                }
-            }
-        } else {
-            ParsedNameDirective::NoMatch
+        if !line.as_bytes().starts_with(prefix.as_bytes()) {
+            return ParsedNameDirective::NoMatch;
         }
+        if line.as_bytes().get(prefix.len()) != Some(&b'-') {
+            return ParsedNameDirective::NoMatch;
+        }
+
+        let name = line[prefix.len() + 1..].split(&[':', ' '][..]).next().unwrap();
+
+        let is_match = name == "test" ||
+            &self.target == name ||                             // triple
+            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
+            (self.target != self.host && name == "cross-compile") ||
+            match self.compare_mode {
+                Some(CompareMode::Nll) => name == "compare-mode-nll",
+                Some(CompareMode::Polonius) => name == "compare-mode-polonius",
+                None => false,
+            } ||
+            (cfg!(debug_assertions) && name == "debug") ||
+            match self.debugger {
+                Some(Debugger::Cdb) => name == "cdb",
+                Some(Debugger::Gdb) => name == "gdb",
+                Some(Debugger::Lldb) => name == "lldb",
+                None => false,
+            };
+
+        if is_match { ParsedNameDirective::Match } else { ParsedNameDirective::NoMatch }
     }
 
     fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index da1e376..5f8aa01 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,13 +1,14 @@
 #![crate_name = "compiletest"]
-#![feature(test)]
+#![feature(vec_remove_item)]
 #![deny(warnings)]
+// The `test` crate is the only unstable feature
+// allowed here, just to share similar code.
+#![feature(test)]
 
 extern crate test;
 
 use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
-use crate::common::{CompareMode, PassMode};
-use crate::common::{Config, TestPaths};
-use crate::common::{DebugInfoCdb, DebugInfoGdb, DebugInfoGdbLldb, DebugInfoLldb, Mode, Pretty};
+use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, Pretty, TestPaths};
 use crate::util::logv;
 use env_logger;
 use getopts;
@@ -23,7 +24,7 @@
 use test::ColorConfig;
 use walkdir::WalkDir;
 
-use self::header::{EarlyProps, Ignore};
+use self::header::EarlyProps;
 
 #[cfg(test)]
 mod tests;
@@ -47,7 +48,7 @@
     }
 
     log_config(&config);
-    run_tests(&config);
+    run_tests(config);
 }
 
 pub fn parse_config(args: Vec<String>) -> Config {
@@ -196,6 +197,7 @@
         build_base: opt_path(matches, "build-base"),
         stage_id: matches.opt_str("stage-id").unwrap(),
         mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"),
+        debugger: None,
         run_ignored,
         filter: matches.free.first().cloned(),
         filter_exact: matches.opt_present("exact"),
@@ -290,61 +292,7 @@
     }
 }
 
-pub fn run_tests(config: &Config) {
-    if config.target.contains("android") {
-        if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb {
-            println!(
-                "{} debug-info test uses tcp 5039 port.\
-                 please reserve it",
-                config.target
-            );
-
-            // android debug-info test uses remote debugger so, we test 1 thread
-            // at once as they're all sharing the same TCP port to communicate
-            // over.
-            //
-            // we should figure out how to lift this restriction! (run them all
-            // on different ports allocated dynamically).
-            env::set_var("RUST_TEST_THREADS", "1");
-        }
-    }
-
-    match config.mode {
-        // Note that we don't need to emit the gdb warning when
-        // DebugInfoGdbLldb, so it is ok to list that here.
-        DebugInfoGdbLldb | DebugInfoLldb => {
-            if let Some(lldb_version) = config.lldb_version.as_ref() {
-                if is_blacklisted_lldb_version(&lldb_version[..]) {
-                    println!(
-                        "WARNING: The used version of LLDB ({}) has a \
-                         known issue that breaks debuginfo tests. See \
-                         issue #32520 for more information. Skipping all \
-                         LLDB-based tests!",
-                        lldb_version
-                    );
-                    return;
-                }
-            }
-
-            // Some older versions of LLDB seem to have problems with multiple
-            // instances running in parallel, so only run one test thread at a
-            // time.
-            env::set_var("RUST_TEST_THREADS", "1");
-        }
-
-        DebugInfoGdb => {
-            if config.remote_test_client.is_some() && !config.target.contains("android") {
-                println!(
-                    "WARNING: debuginfo tests are not available when \
-                     testing with remote"
-                );
-                return;
-            }
-        }
-
-        DebugInfoCdb | _ => { /* proceed */ }
-    }
-
+pub fn run_tests(config: Config) {
     // FIXME(#33435) Avoid spurious failures in codegen-units/partitioning tests.
     if let Mode::CodegenUnits = config.mode {
         let _ = fs::remove_dir_all("tmp/partitioning-tests");
@@ -363,8 +311,6 @@
         }
     }
 
-    let opts = test_opts(config);
-    let tests = make_tests(config);
     // sadly osx needs some file descriptor limits raised for running tests in
     // parallel (especially when we have lots and lots of child processes).
     // For context, see #8904
@@ -378,6 +324,25 @@
     // Let tests know which target they're running as
     env::set_var("TARGET", &config.target);
 
+    let opts = test_opts(&config);
+
+    let mut configs = Vec::new();
+    if let Mode::DebugInfo = config.mode {
+        // Debugging emscripten code doesn't make sense today
+        if !config.target.contains("emscripten") {
+            configs.extend(configure_cdb(&config));
+            configs.extend(configure_gdb(&config));
+            configs.extend(configure_lldb(&config));
+        }
+    } else {
+        configs.push(config);
+    };
+
+    let mut tests = Vec::new();
+    for c in &configs {
+        make_tests(c, &mut tests);
+    }
+
     let res = test::run_tests_console(&opts, tests);
     match res {
         Ok(true) => {}
@@ -388,6 +353,76 @@
     }
 }
 
+fn configure_cdb(config: &Config) -> Option<Config> {
+    if config.cdb.is_none() {
+        return None;
+    }
+
+    Some(Config { debugger: Some(Debugger::Cdb), ..config.clone() })
+}
+
+fn configure_gdb(config: &Config) -> Option<Config> {
+    if config.gdb_version.is_none() {
+        return None;
+    }
+
+    if util::matches_env(&config.target, "msvc") {
+        return None;
+    }
+
+    if config.remote_test_client.is_some() && !config.target.contains("android") {
+        println!(
+            "WARNING: debuginfo tests are not available when \
+             testing with remote"
+        );
+        return None;
+    }
+
+    if config.target.contains("android") {
+        println!(
+            "{} debug-info test uses tcp 5039 port.\
+             please reserve it",
+            config.target
+        );
+
+        // android debug-info test uses remote debugger so, we test 1 thread
+        // at once as they're all sharing the same TCP port to communicate
+        // over.
+        //
+        // we should figure out how to lift this restriction! (run them all
+        // on different ports allocated dynamically).
+        env::set_var("RUST_TEST_THREADS", "1");
+    }
+
+    Some(Config { debugger: Some(Debugger::Gdb), ..config.clone() })
+}
+
+fn configure_lldb(config: &Config) -> Option<Config> {
+    if config.lldb_python_dir.is_none() {
+        return None;
+    }
+
+    if let Some(lldb_version) = config.lldb_version.as_ref() {
+        if is_blacklisted_lldb_version(&lldb_version) {
+            println!(
+                "WARNING: The used version of LLDB ({}) has a \
+                 known issue that breaks debuginfo tests. See \
+                 issue #32520 for more information. Skipping all \
+                 LLDB-based tests!",
+                lldb_version
+            );
+            return None;
+        }
+    }
+
+    // Some older versions of LLDB seem to have problems with multiple
+    // instances running in parallel, so only run one test thread at a
+    // time.
+    env::set_var("RUST_TEST_THREADS", "1");
+
+    Some(Config { debugger: Some(Debugger::Lldb), ..config.clone() })
+}
+
 pub fn test_opts(config: &Config) -> test::TestOpts {
     test::TestOpts {
         exclude_should_panic: false,
@@ -412,20 +447,18 @@
     }
 }
 
-pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> {
+pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
     debug!("making tests from {:?}", config.src_base.display());
     let inputs = common_inputs_stamp(config);
-    let mut tests = Vec::new();
     collect_tests_from_dir(
         config,
         &config.src_base,
         &config.src_base,
         &PathBuf::new(),
         &inputs,
-        &mut tests,
+        tests,
     )
     .expect(&format!("Could not read tests from {}", config.src_base.display()));
-    tests
 }
 
 /// Returns a stamp constructed from input files common to all test cases.
@@ -567,13 +600,7 @@
     revisions
         .into_iter()
         .map(|revision| {
-            let ignore = early_props.ignore == Ignore::Ignore
-                // Debugging emscripten code doesn't make sense today
-                || ((config.mode == DebugInfoGdbLldb || config.mode == DebugInfoCdb ||
-                     config.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
-                    && config.target.contains("emscripten"))
-                || (config.mode == DebugInfoGdb && !early_props.ignore.can_run_gdb())
-                || (config.mode == DebugInfoLldb && !early_props.ignore.can_run_lldb())
+            let ignore = early_props.ignore
                 // Ignore tests that already run and are up to date with respect to inputs.
                 || is_up_to_date(
                     config,
@@ -590,7 +617,7 @@
                     allow_fail: false,
                     test_type: test::TestType::Unknown,
                 },
-                testfn: make_test_closure(config, early_props.ignore, testpaths, revision),
+                testfn: make_test_closure(config, testpaths, revision),
             }
         })
         .collect()
@@ -621,7 +648,8 @@
 
     // Check timestamps.
     let mut inputs = inputs.clone();
-    inputs.add_path(&testpaths.file);
+    // Use `add_dir` to account for run-make tests, which use their individual directory
+    inputs.add_dir(&testpaths.file);
 
     for aux in &props.aux {
         let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
@@ -682,13 +710,19 @@
     let path = PathBuf::from(config.src_base.file_name().unwrap())
         .join(&testpaths.relative_dir)
         .join(&testpaths.file.file_name().unwrap());
+    let debugger = match config.debugger {
+        Some(d) => format!("-{}", d),
+        None => String::new(),
+    };
     let mode_suffix = match config.compare_mode {
         Some(ref mode) => format!(" ({})", mode.to_str()),
         None => String::new(),
     };
+
     test::DynTestName(format!(
-        "[{}{}] {}{}",
+        "[{}{}{}] {}{}",
         config.mode,
+        debugger,
         mode_suffix,
         path.display(),
         revision.map_or("".to_string(), |rev| format!("#{}", rev))
@@ -697,21 +731,10 @@
 
 fn make_test_closure(
     config: &Config,
-    ignore: Ignore,
     testpaths: &TestPaths,
     revision: Option<&String>,
 ) -> test::TestFn {
-    let mut config = config.clone();
-    if config.mode == DebugInfoGdbLldb {
-        // If both gdb and lldb were ignored, then the test as a whole
-        // would be ignored.
-        if !ignore.can_run_gdb() {
-            config.mode = DebugInfoLldb;
-        } else if !ignore.can_run_lldb() {
-            config.mode = DebugInfoGdb;
-        }
-    }
-
+    let config = config.clone();
     let testpaths = testpaths.clone();
     let revision = revision.cloned();
     test::DynTestFn(Box::new(move || {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 226a12c..d1ee60d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3,11 +3,10 @@
 use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
 use crate::common::{output_base_dir, output_base_name, output_testname_unique};
 use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, Ui};
-use crate::common::{Codegen, CodegenUnits, Rustdoc};
+use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
 use crate::common::{CompareMode, FailMode, PassMode};
 use crate::common::{CompileFail, Pretty, RunFail, RunPassValgrind};
 use crate::common::{Config, TestPaths};
-use crate::common::{DebugInfoCdb, DebugInfoGdb, DebugInfoGdbLldb, DebugInfoLldb};
 use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
@@ -42,10 +41,8 @@
 #[cfg(windows)]
 fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
     use std::sync::Mutex;
-    const SEM_NOGPFAULTERRORBOX: u32 = 0x0002;
-    extern "system" {
-        fn SetErrorMode(mode: u32) -> u32;
-    }
+    use winapi::um::errhandlingapi::SetErrorMode;
+    use winapi::um::winbase::SEM_NOGPFAULTERRORBOX;
 
     lazy_static! {
         static ref LOCK: Mutex<()> = { Mutex::new(()) };
@@ -194,7 +191,7 @@
 
         _ => {
             // android has its own gdb handling
-            if config.mode == DebugInfoGdb && config.gdb.is_none() {
+            if config.debugger == Some(Debugger::Gdb) && config.gdb.is_none() {
                 panic!("gdb not available but debuginfo gdb debuginfo test requested");
             }
         }
@@ -236,21 +233,25 @@
     let mut hash = DefaultHasher::new();
     config.stage_id.hash(&mut hash);
 
-    if config.mode == DebugInfoCdb {
-        config.cdb.hash(&mut hash);
-    }
+    match config.debugger {
+        Some(Debugger::Cdb) => {
+            config.cdb.hash(&mut hash);
+        }
 
-    if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb {
-        match config.gdb {
-            None => env::var_os("PATH").hash(&mut hash),
-            Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash),
-            Some(ref s) => s.hash(&mut hash),
-        };
-    }
+        Some(Debugger::Gdb) => {
+            config.gdb.hash(&mut hash);
+            env::var_os("PATH").hash(&mut hash);
+            env::var_os("PYTHONPATH").hash(&mut hash);
+        }
 
-    if config.mode == DebugInfoLldb || config.mode == DebugInfoGdbLldb {
-        env::var_os("PATH").hash(&mut hash);
-        env::var_os("PYTHONPATH").hash(&mut hash);
+        Some(Debugger::Lldb) => {
+            config.lldb_python.hash(&mut hash);
+            config.lldb_python_dir.hash(&mut hash);
+            env::var_os("PATH").hash(&mut hash);
+            env::var_os("PYTHONPATH").hash(&mut hash);
+        }
+
+        None => {}
     }
 
     if let Ui = config.mode {
@@ -311,13 +312,7 @@
             RunFail => self.run_rfail_test(),
             RunPassValgrind => self.run_valgrind_test(),
             Pretty => self.run_pretty_test(),
-            DebugInfoGdbLldb => {
-                self.run_debuginfo_gdb_test();
-                self.run_debuginfo_lldb_test();
-            }
-            DebugInfoCdb => self.run_debuginfo_cdb_test(),
-            DebugInfoGdb => self.run_debuginfo_gdb_test(),
-            DebugInfoLldb => self.run_debuginfo_lldb_test(),
+            DebugInfo => self.run_debuginfo_test(),
             Codegen => self.run_codegen_test(),
             Rustdoc => self.run_rustdoc_test(),
             CodegenUnits => self.run_codegen_units_test(),
@@ -682,13 +677,20 @@
         self.compose_and_run_compiler(rustc, Some(src))
     }
 
+    fn run_debuginfo_test(&self) {
+        match self.config.debugger.unwrap() {
+            Debugger::Cdb => self.run_debuginfo_cdb_test(),
+            Debugger::Gdb => self.run_debuginfo_gdb_test(),
+            Debugger::Lldb => self.run_debuginfo_lldb_test(),
+        }
+    }
+
     fn run_debuginfo_cdb_test(&self) {
         assert!(self.revision.is_none(), "revisions not relevant here");
 
         let config = Config {
             target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
             host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            mode: DebugInfoCdb,
             ..self.config.clone()
         };
 
@@ -767,7 +769,6 @@
         let config = Config {
             target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
             host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            mode: DebugInfoGdb,
             ..self.config.clone()
         };
 
@@ -1001,7 +1002,6 @@
         let config = Config {
             target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
             host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            mode: DebugInfoLldb,
             ..self.config.clone()
         };
 
@@ -1864,12 +1864,14 @@
                     rustc.args(&["--error-format", "json"]);
                 }
                 rustc.arg("-Zui-testing");
+                rustc.arg("-Zdeduplicate-diagnostics=no");
             }
             Ui => {
                 if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) {
                     rustc.args(&["--error-format", "json"]);
                 }
                 rustc.arg("-Zui-testing");
+                rustc.arg("-Zdeduplicate-diagnostics=no");
             }
             MirOpt => {
                 rustc.args(&[
@@ -1887,8 +1889,8 @@
 
                 rustc.arg(dir_opt);
             }
-            RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb
-            | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => {
+            RunFail | RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RunMake
+            | CodegenUnits | JsDocTest | Assembly => {
                 // do not use JSON output
             }
         }
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 003f51a..2663b3d 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -67,6 +67,7 @@
     ("powerpc", "powerpc"),
     ("powerpc64", "powerpc64"),
     ("powerpc64le", "powerpc64"),
+    ("riscv64gc", "riscv64"),
     ("s390x", "s390x"),
     ("sparc", "sparc"),
     ("sparc64", "sparc64"),
diff --git a/src/tools/miri b/src/tools/miri
index 4e44aa0..6a0f14b 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 4e44aa010c4c7d616182a3078cafb39da6f6c0a2
+Subproject commit 6a0f14bef7784e57a57a996cae3f94dbd2490e7a
diff --git a/src/tools/rls b/src/tools/rls
index 7c0489c..b27e117 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 7c0489c5ff4f5c594e65a3b22efd9ce373deab9b
+Subproject commit b27e1173969639448cd2e486b1c5f0fcb1b3b17c
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index fced6c5..936e8ae 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -65,7 +65,7 @@
 smallvec-0_6 = { package = "smallvec", version = "0.6", features = ['union', 'may_dangle'] }
 smallvec = { version = "1.0", features = ['union', 'may_dangle'] }
 url = { version = "2.0", features = ['serde'] }
-syn = { version = "0.15", features = ['full'] }
+syn = { version = "0.15", features = ['full', 'extra-traits'] }
 
 [target.'cfg(not(windows))'.dependencies]
 openssl = { version = "0.10.12", optional = true }
diff --git a/src/tools/tidy/src/debug_artifacts.rs b/src/tools/tidy/src/debug_artifacts.rs
index 4664e2e..408be83 100644
--- a/src/tools/tidy/src/debug_artifacts.rs
+++ b/src/tools/tidy/src/debug_artifacts.rs
@@ -2,7 +2,7 @@
 
 use std::path::{Path, PathBuf};
 
-const GRAPHVIZ_POSTFLOW_MSG: &'static str = "`borrowck_graphviz_postflow` attribute in test";
+const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test";
 
 pub fn check(path: &Path, bad: &mut bool) {
     let test_dir: PathBuf = path.join("test");
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index ebaa81d..428c57d 100644
--- a/src/tools/tidy/src/error_codes_check.rs
+++ b/src/tools/tidy/src/error_codes_check.rs
@@ -53,7 +53,7 @@
                     error_codes.insert(err_code.clone(), false);
                 }
                 // Now we extract the tests from the markdown file!
-                let md = some_or_continue!(s.splitn(2, "include_str!(\"").skip(1).next());
+                let md = some_or_continue!(s.splitn(2, "include_str!(\"").nth(1));
                 let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
                 let path = some_or_continue!(path.parent()).join(md_file_name);
                 match read_to_string(&path) {
@@ -84,7 +84,7 @@
         let s = line.trim();
         if s.starts_with("error[E") || s.starts_with("warning[E") {
             if let Some(err_code) = s.splitn(2, ']').next() {
-                if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() {
+                if let Some(err_code) = err_code.splitn(2, '[').nth(1) {
                     let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
                     *nb = true;
                 }
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 325b45e..12f93a8 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -232,7 +232,7 @@
             }
         }
     }
-    return false;
+    false
 }
 
 pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features {
@@ -344,7 +344,7 @@
                 }
                 None
             } else {
-                let s = issue_str.split('(').nth(1).unwrap().split(')').nth(0).unwrap();
+                let s = issue_str.split('(').nth(1).unwrap().split(')').next().unwrap();
                 Some(s.parse().unwrap())
             };
             Some((name.to_owned(), Feature { level, since, has_gate_test: false, tracking_issue }))
diff --git a/src/tools/tidy/src/features/version.rs b/src/tools/tidy/src/features/version.rs
index c8c39ad..620be2f 100644
--- a/src/tools/tidy/src/features/version.rs
+++ b/src/tools/tidy/src/features/version.rs
@@ -38,7 +38,7 @@
 
         let parts = [part()?, part()?, part()?];
 
-        if let Some(_) = iter.next() {
+        if iter.next().is_some() {
             // Ensure we don't have more than 3 parts.
             return Err(ParseVersionError::WrongNumberOfParts);
         }
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index b15c299..4247fcb3b 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -58,7 +58,7 @@
 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");
+        return line.starts_with('[') && line.contains("]:") && line.contains("http");
     }
 
     use self::LIUState::*;
diff --git a/src/tools/unicode-table-generator/Cargo.toml b/src/tools/unicode-table-generator/Cargo.toml
new file mode 100644
index 0000000..92344cd
--- /dev/null
+++ b/src/tools/unicode-table-generator/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "unicode-bdd"
+version = "0.1.0"
+authors = ["Mark Rousskov <mark.simulacrum@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+ucd-parse = "0.1.3"
diff --git a/src/tools/unicode-table-generator/src/case_mapping.rs b/src/tools/unicode-table-generator/src/case_mapping.rs
new file mode 100644
index 0000000..01f199c
--- /dev/null
+++ b/src/tools/unicode-table-generator/src/case_mapping.rs
@@ -0,0 +1,62 @@
+use crate::{fmt_list, UnicodeData};
+use std::fmt;
+
+pub(crate) fn generate_case_mapping(data: &UnicodeData) -> String {
+    let mut file = String::new();
+
+    file.push_str(HEADER.trim_start());
+
+    let decl_type = "&[(char, [char; 3])]";
+
+    file.push_str(&format!(
+        "static LOWERCASE_TABLE: {} = &[{}];",
+        decl_type,
+        fmt_list(data.to_lower.iter().map(to_mapping))
+    ));
+    file.push_str("\n\n");
+    file.push_str(&format!(
+        "static UPPERCASE_TABLE: {} = &[{}];",
+        decl_type,
+        fmt_list(data.to_upper.iter().map(to_mapping))
+    ));
+    file
+}
+
+fn to_mapping((key, (a, b, c)): (&u32, &(u32, u32, u32))) -> (CharEscape, [CharEscape; 3]) {
+    (
+        CharEscape(std::char::from_u32(*key).unwrap()),
+        [
+            CharEscape(std::char::from_u32(*a).unwrap()),
+            CharEscape(std::char::from_u32(*b).unwrap()),
+            CharEscape(std::char::from_u32(*c).unwrap()),
+        ],
+    )
+}
+
+struct CharEscape(char);
+
+impl fmt::Debug for CharEscape {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "'{}'", self.0.escape_default())
+    }
+}
+
+static HEADER: &str = "
+pub fn to_lower(c: char) -> [char; 3] {
+    match bsearch_case_table(c, LOWERCASE_TABLE) {
+        None => [c, '\\0', '\\0'],
+        Some(index) => LOWERCASE_TABLE[index].1,
+    }
+}
+
+pub fn to_upper(c: char) -> [char; 3] {
+    match bsearch_case_table(c, UPPERCASE_TABLE) {
+        None => [c, '\\0', '\\0'],
+        Some(index) => UPPERCASE_TABLE[index].1,
+    }
+}
+
+fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
+    table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
+}
+";
diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs
new file mode 100644
index 0000000..be8508e
--- /dev/null
+++ b/src/tools/unicode-table-generator/src/main.rs
@@ -0,0 +1,261 @@
+use std::collections::{BTreeMap, HashMap};
+use std::ops::Range;
+use ucd_parse::Codepoints;
+
+mod case_mapping;
+mod raw_emitter;
+mod unicode_download;
+
+use raw_emitter::{emit_codepoints, RawEmitter};
+
+static PROPERTIES: &[&str] = &[
+    "Alphabetic",
+    "Lowercase",
+    "Uppercase",
+    "Cased",
+    "Case_Ignorable",
+    "Grapheme_Extend",
+    "White_Space",
+    "Cc",
+    "N",
+];
+
+struct UnicodeData {
+    ranges: Vec<(&'static str, Vec<Range<u32>>)>,
+    to_upper: BTreeMap<u32, (u32, u32, u32)>,
+    to_lower: BTreeMap<u32, (u32, u32, u32)>,
+}
+
+fn to_mapping(origin: u32, codepoints: Vec<ucd_parse::Codepoint>) -> Option<(u32, u32, u32)> {
+    let mut a = None;
+    let mut b = None;
+    let mut c = None;
+
+    for codepoint in codepoints {
+        if origin == codepoint.value() {
+            return None;
+        }
+
+        if a.is_none() {
+            a = Some(codepoint.value());
+        } else if b.is_none() {
+            b = Some(codepoint.value());
+        } else if c.is_none() {
+            c = Some(codepoint.value());
+        } else {
+            panic!("more than 3 mapped codepoints")
+        }
+    }
+
+    Some((a.unwrap(), b.unwrap_or(0), c.unwrap_or(0)))
+}
+
+static UNICODE_DIRECTORY: &str = "unicode-downloads";
+
+fn load_data() -> UnicodeData {
+    unicode_download::fetch_latest();
+
+    let mut properties = HashMap::new();
+    for row in ucd_parse::parse::<_, ucd_parse::CoreProperty>(&UNICODE_DIRECTORY).unwrap() {
+        if let Some(name) = PROPERTIES.iter().find(|prop| **prop == row.property.as_str()) {
+            properties.entry(*name).or_insert_with(Vec::new).push(row.codepoints);
+        }
+    }
+    for row in ucd_parse::parse::<_, ucd_parse::Property>(&UNICODE_DIRECTORY).unwrap() {
+        if let Some(name) = PROPERTIES.iter().find(|prop| **prop == row.property.as_str()) {
+            properties.entry(*name).or_insert_with(Vec::new).push(row.codepoints);
+        }
+    }
+
+    let mut to_lower = BTreeMap::new();
+    let mut to_upper = BTreeMap::new();
+    for row in ucd_parse::UnicodeDataExpander::new(
+        ucd_parse::parse::<_, ucd_parse::UnicodeData>(&UNICODE_DIRECTORY).unwrap(),
+    ) {
+        let general_category = if ["Nd", "Nl", "No"].contains(&row.general_category.as_str()) {
+            "N"
+        } else {
+            row.general_category.as_str()
+        };
+        if let Some(name) = PROPERTIES.iter().find(|prop| **prop == general_category) {
+            properties
+                .entry(*name)
+                .or_insert_with(Vec::new)
+                .push(Codepoints::Single(row.codepoint));
+        }
+
+        if let Some(mapped) = row.simple_lowercase_mapping {
+            if mapped != row.codepoint {
+                to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
+            }
+        }
+        if let Some(mapped) = row.simple_uppercase_mapping {
+            if mapped != row.codepoint {
+                to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
+            }
+        }
+    }
+
+    for row in ucd_parse::parse::<_, ucd_parse::SpecialCaseMapping>(&UNICODE_DIRECTORY).unwrap() {
+        if !row.conditions.is_empty() {
+            // Skip conditional case mappings
+            continue;
+        }
+
+        let key = row.codepoint.value();
+        if let Some(lower) = to_mapping(key, row.lowercase) {
+            to_lower.insert(key, lower);
+        }
+        if let Some(upper) = to_mapping(key, row.uppercase) {
+            to_upper.insert(key, upper);
+        }
+    }
+
+    let mut properties: HashMap<&'static str, Vec<Range<u32>>> = properties
+        .into_iter()
+        .map(|(k, v)| {
+            (
+                k,
+                v.into_iter()
+                    .flat_map(|codepoints| match codepoints {
+                        Codepoints::Single(c) => c
+                            .scalar()
+                            .map(|ch| (ch as u32..ch as u32 + 1))
+                            .into_iter()
+                            .collect::<Vec<_>>(),
+                        Codepoints::Range(c) => c
+                            .into_iter()
+                            .flat_map(|c| c.scalar().map(|ch| (ch as u32..ch as u32 + 1)))
+                            .collect::<Vec<_>>(),
+                    })
+                    .collect::<Vec<Range<u32>>>(),
+            )
+        })
+        .collect();
+
+    for ranges in properties.values_mut() {
+        merge_ranges(ranges);
+    }
+
+    let mut properties = properties.into_iter().collect::<Vec<_>>();
+    properties.sort_by_key(|p| p.0);
+    UnicodeData { ranges: properties, to_lower, to_upper }
+}
+
+fn main() {
+    let write_location = std::env::args().nth(1).unwrap_or_else(|| {
+        eprintln!("Must provide path to write unicode tables to");
+        eprintln!(
+            "e.g. {} src/libcore/unicode/unicode_data.rs",
+            std::env::args().nth(0).unwrap_or_default()
+        );
+        std::process::exit(1);
+    });
+
+    let unicode_data = load_data();
+    let ranges_by_property = &unicode_data.ranges;
+
+    let mut total_bytes = 0;
+    let mut modules = Vec::new();
+    for (property, ranges) in ranges_by_property {
+        let datapoints = ranges.iter().map(|r| r.end - r.start).sum::<u32>();
+        let mut emitter = RawEmitter::new();
+        emit_codepoints(&mut emitter, &ranges);
+
+        modules.push((property.to_lowercase().to_string(), emitter.file));
+        println!("{:15}: {} bytes, {} codepoints", property, emitter.bytes_used, datapoints,);
+        total_bytes += emitter.bytes_used;
+    }
+
+    let mut table_file = String::new();
+
+    table_file.push_str(
+        "///! This file is generated by src/tools/unicode-table-generator; do not edit manually!\n",
+    );
+
+    table_file.push_str("use super::range_search;\n\n");
+
+    table_file.push_str(&version());
+
+    table_file.push('\n');
+
+    modules.push((String::from("conversions"), case_mapping::generate_case_mapping(&unicode_data)));
+
+    for (name, contents) in modules {
+        table_file.push_str("#[rustfmt::skip]\n");
+        table_file.push_str(&format!("pub mod {} {{\n", name));
+        for line in contents.lines() {
+            if !line.trim().is_empty() {
+                table_file.push_str("    ");
+                table_file.push_str(&line);
+            }
+            table_file.push('\n');
+        }
+        table_file.push_str("}\n\n");
+    }
+
+    std::fs::write(&write_location, format!("{}\n", table_file.trim_end())).unwrap();
+
+    println!("Total table sizes: {} bytes", total_bytes);
+}
+
+fn version() -> String {
+    let mut out = String::new();
+    out.push_str("pub const UNICODE_VERSION: (u32, u32, u32) = ");
+
+    let readme =
+        std::fs::read_to_string(std::path::Path::new(UNICODE_DIRECTORY).join("ReadMe.txt"))
+            .unwrap();
+
+    let prefix = "for Version ";
+    let start = readme.find(prefix).unwrap() + prefix.len();
+    let end = readme.find(" of the Unicode Standard.").unwrap();
+    let version =
+        readme[start..end].split('.').map(|v| v.parse::<u32>().expect(&v)).collect::<Vec<_>>();
+    let [major, minor, micro] = [version[0], version[1], version[2]];
+
+    out.push_str(&format!("({}, {}, {});\n", major, minor, micro));
+    out
+}
+
+fn fmt_list<V: std::fmt::Debug>(values: impl IntoIterator<Item = V>) -> String {
+    let pieces = values.into_iter().map(|b| format!("{:?}, ", b)).collect::<Vec<_>>();
+    let mut out = String::new();
+    let mut line = format!("\n    ");
+    for piece in pieces {
+        if line.len() + piece.len() < 98 {
+            line.push_str(&piece);
+        } else {
+            out.push_str(line.trim_end());
+            out.push('\n');
+            line = format!("    {}", piece);
+        }
+    }
+    out.push_str(line.trim_end());
+    out.push('\n');
+    out
+}
+
+fn merge_ranges(ranges: &mut Vec<Range<u32>>) {
+    loop {
+        let mut new_ranges = Vec::new();
+        let mut idx_iter = 0..(ranges.len() - 1);
+        while let Some(idx) = idx_iter.next() {
+            let cur = ranges[idx].clone();
+            let next = ranges[idx + 1].clone();
+            if cur.end == next.start {
+                let _ = idx_iter.next(); // skip next as we're merging it in
+                new_ranges.push(cur.start..next.end);
+            } else {
+                new_ranges.push(cur);
+            }
+        }
+        new_ranges.push(ranges.last().unwrap().clone());
+        if new_ranges.len() == ranges.len() {
+            *ranges = new_ranges;
+            break;
+        } else {
+            *ranges = new_ranges;
+        }
+    }
+}
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
new file mode 100644
index 0000000..3e60ce1
--- /dev/null
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -0,0 +1,170 @@
+//! This implements the core logic of the compression scheme used to compactly
+//! encode the Unicode character classes.
+//!
+//! The primary idea is that we 'flatten' the Unicode ranges into an enormous
+//! bitset. To represent any arbitrary codepoint in a raw bitset, we would need
+//! over 17 kilobytes of data per character set -- way too much for our
+//! purposes.
+//!
+//! We have two primary goals with the encoding: we want to be compact, because
+//! these tables often end up in ~every Rust program (especially the
+//! grapheme_extend table, used for str debugging), including those for embedded
+//! targets (where space is important). We also want to be relatively fast,
+//! though this is more of a nice to have rather than a key design constraint.
+//! In practice, due to modern processor design these two are closely related.
+//!
+//! The encoding scheme here compresses the bitset by first deduplicating the
+//! "words" (64 bits on all platforms). In practice very few words are present
+//! in most data sets.
+//!
+//! This gives us an array that maps `u8 -> word` (if we ever went beyond 256
+//! words, we could go to u16 -> word or have some dual compression scheme
+//! mapping into two separate sets; currently this is not dealt with).
+//!
+//! With that scheme, we now have a single byte for every 64 codepoints. We
+//! further group these by 16 (arbitrarily chosen), and again deduplicate and
+//! store in an array (u8 -> [u8; 16]).
+//!
+//! The indices into this array represent ranges of 64*16 = 1024 codepoints.
+//!
+//! This already reduces the top-level array to at most 1,086 bytes, but in
+//! practice we usually can encode in far fewer (the first couple Unicode planes
+//! are dense).
+//!
+//! The last byte of this top-level array is pulled out to a separate static
+//! and trailing zeros are dropped; this is simply because grapheme_extend and
+//! case_ignorable have a single entry in the 896th entry, so this shrinks them
+//! down considerably.
+
+use crate::fmt_list;
+use std::collections::{BTreeSet, HashMap};
+use std::convert::TryFrom;
+use std::fmt::Write;
+use std::ops::Range;
+
+pub struct RawEmitter {
+    pub file: String,
+    pub bytes_used: usize,
+}
+
+impl RawEmitter {
+    pub fn new() -> RawEmitter {
+        RawEmitter { file: String::new(), bytes_used: 0 }
+    }
+
+    fn blank_line(&mut self) {
+        if self.file.is_empty() || self.file.ends_with("\n\n") {
+            return;
+        }
+        writeln!(&mut self.file, "").unwrap();
+    }
+
+    fn emit_bitset(&mut self, words: &[u64]) {
+        let unique_words =
+            words.iter().cloned().collect::<BTreeSet<_>>().into_iter().collect::<Vec<_>>();
+        if unique_words.len() > u8::max_value() as usize {
+            panic!("cannot pack {} into 8 bits", unique_words.len());
+        }
+
+        let word_indices = unique_words
+            .iter()
+            .cloned()
+            .enumerate()
+            .map(|(idx, word)| (word, u8::try_from(idx).unwrap()))
+            .collect::<HashMap<_, _>>();
+
+        let mut idx = words.iter().map(|w| word_indices[w]).collect::<Vec<u8>>();
+        let chunk_length = 16;
+        for _ in 0..(chunk_length - (idx.len() % chunk_length)) {
+            assert_eq!(unique_words[0], 0, "first word is all zeros");
+            // pad out bitset index with zero words so we have all chunks of 16
+            idx.push(0);
+        }
+
+        let mut chunks = BTreeSet::new();
+        for chunk in idx.chunks(chunk_length) {
+            chunks.insert(chunk);
+        }
+        let chunk_map = chunks
+            .clone()
+            .into_iter()
+            .enumerate()
+            .map(|(idx, chunk)| (chunk, idx))
+            .collect::<HashMap<_, _>>();
+        let mut chunk_indices = Vec::new();
+        for chunk in idx.chunks(chunk_length) {
+            chunk_indices.push(chunk_map[chunk]);
+        }
+        writeln!(
+            &mut self.file,
+            "static BITSET_LAST_CHUNK_MAP: (u16, u8) = ({}, {});",
+            chunk_indices.len() - 1,
+            chunk_indices.pop().unwrap(),
+        )
+        .unwrap();
+        self.bytes_used += 3;
+        // Strip out the empty pieces, presuming our above pop() made us now
+        // have some trailing zeros.
+        assert_eq!(unique_words[0], 0, "first word is all zeros");
+        while let Some(0) = chunk_indices.last() {
+            chunk_indices.pop();
+        }
+        writeln!(
+            &mut self.file,
+            "static BITSET_CHUNKS_MAP: [u8; {}] = [{}];",
+            chunk_indices.len(),
+            fmt_list(&chunk_indices),
+        )
+        .unwrap();
+        self.bytes_used += chunk_indices.len();
+        writeln!(
+            &mut self.file,
+            "static BITSET_INDEX_CHUNKS: [[u8; 16]; {}] = [{}];",
+            chunks.len(),
+            fmt_list(chunks.iter()),
+        )
+        .unwrap();
+        self.bytes_used += 16 * chunks.len();
+        writeln!(
+            &mut self.file,
+            "static BITSET: [u64; {}] = [{}];",
+            unique_words.len(),
+            fmt_list(&unique_words),
+        )
+        .unwrap();
+        self.bytes_used += 8 * unique_words.len();
+    }
+
+    pub fn emit_lookup(&mut self) {
+        writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap();
+        writeln!(&mut self.file, "    super::range_search(",).unwrap();
+        writeln!(&mut self.file, "        c as u32,").unwrap();
+        writeln!(&mut self.file, "        &BITSET_CHUNKS_MAP,").unwrap();
+        writeln!(&mut self.file, "        BITSET_LAST_CHUNK_MAP,").unwrap();
+        writeln!(&mut self.file, "        &BITSET_INDEX_CHUNKS,").unwrap();
+        writeln!(&mut self.file, "        &BITSET,").unwrap();
+        writeln!(&mut self.file, "    )").unwrap();
+        writeln!(&mut self.file, "}}").unwrap();
+    }
+}
+
+pub fn emit_codepoints(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
+    emitter.blank_line();
+
+    let last_code_point = ranges.last().unwrap().end;
+    // bitset for every bit in the codepoint range
+    //
+    // + 2 to ensure an all zero word to use for padding
+    let mut buckets = vec![0u64; (last_code_point as usize / 64) + 2];
+    for range in ranges {
+        for codepoint in range.clone() {
+            let bucket = codepoint as usize / 64;
+            let bit = codepoint as u64 % 64;
+            buckets[bucket] |= 1 << bit;
+        }
+    }
+
+    emitter.emit_bitset(&buckets);
+    emitter.blank_line();
+    emitter.emit_lookup();
+}
diff --git a/src/tools/unicode-table-generator/src/unicode_download.rs b/src/tools/unicode-table-generator/src/unicode_download.rs
new file mode 100644
index 0000000..3f6de9e
--- /dev/null
+++ b/src/tools/unicode-table-generator/src/unicode_download.rs
@@ -0,0 +1,42 @@
+use crate::UNICODE_DIRECTORY;
+use std::path::Path;
+use std::process::Command;
+
+static URL_PREFIX: &str = "https://www.unicode.org/Public/UCD/latest/ucd/";
+
+static README: &str = "ReadMe.txt";
+
+static RESOURCES: &[&str] =
+    &["DerivedCoreProperties.txt", "PropList.txt", "UnicodeData.txt", "SpecialCasing.txt"];
+
+pub fn fetch_latest() {
+    let directory = Path::new(UNICODE_DIRECTORY);
+    if let Err(e) = std::fs::create_dir_all(directory) {
+        if e.kind() != std::io::ErrorKind::AlreadyExists {
+            panic!("Failed to create {:?}: {}", UNICODE_DIRECTORY, e);
+        }
+    }
+    let output = Command::new("curl").arg(URL_PREFIX.to_owned() + README).output().unwrap();
+    if !output.status.success() {
+        panic!(
+            "Failed to run curl to fetch readme: stderr: {}",
+            String::from_utf8_lossy(&output.stderr)
+        );
+    }
+    let current = std::fs::read_to_string(directory.join(README)).unwrap_or_default();
+    if current.as_bytes() != &output.stdout[..] {
+        std::fs::write(directory.join(README), output.stdout).unwrap();
+    }
+
+    for resource in RESOURCES {
+        let output = Command::new("curl").arg(URL_PREFIX.to_owned() + resource).output().unwrap();
+        if !output.status.success() {
+            panic!(
+                "Failed to run curl to fetch {}: stderr: {}",
+                resource,
+                String::from_utf8_lossy(&output.stderr)
+            );
+        }
+        std::fs::write(directory.join(resource), output.stdout).unwrap();
+    }
+}